View previous topic :: View next topic
Author
Message
mjadwani2785 New User Joined: 28 Apr 2009Posts: 89 Location: Noida , Dublin
Hi,
I am able to activate admin scheduler of DB2 at my site . The code which I wrote was in batch assigned some static values and it worked fine for me.Job got scheduled and were running fine.
Initial testing went fine used few values to experiment with.
Now I am designing ISPF panel to work this thing out but the code here fails:
the code as follows
Code:
address ispexec
"display panel (panadm2) "
if (length(jcllib)<>0) then
do
do while(length(jclmem)==0 | length(jobwait)==0)
address ispexec
"display "
end
end
if (rc==0) then
call initialise
else
call adieu
call connect_db2
call Add_task
call adieu
adieu:
exit /*bye_bye */
initialise :
/* upper dbssid ; upper jcllib
upper jclmem ; upper jobwait
upper desc */
DB2_SUBSYS='DB2V'
PROC = 'SYSPROC.ADMIN_TASK_ADD'
s_rc = 0
if (length(uid)==0) then i_uid=-1
else i_uid=0
if (length(pwd)==0) then i_pwd=-1
else i_pwd=0
if (length(begts)==0) then i_begts=-1
else i_begts=0
if (length(endts)==0) then i_endts=-1
else i_endts=0
if (length(maxinvo)==0) then i_maxinvo=-1
else i_maxinvo=0
if (length(intval)==0) then i_intval=-1
else intval=0
if (length(pit)==0) then i_pit=-1
else i_pit=0
if (length(ttname)==0) then i_ttname=-1
else i_ttname=0
if (length(ttcond)==0) then i_ttcond=-1
else i_ttcond=0
if (length(ttcode)==0) then i_ttcode=-1
else i_ttcode=0
if (length(dbssid)==0) then i_dbssid=-1
else
i_dbssid=0
if (length(pschema)==0) then
do
pschema=" "
i_pschema=-1
end
else i_pschema=0
if (length(pname)==0) then i_pname=-1
else i_pname=0
if (length(pinput)==0) then i_pinput=-1
else i_pinput=0
if (length(jcllib)==0) then i_jcllib=-1
else i_jcllib=0
if (length(jclmem)==0) then i_jclmem=-1
else i_jclmem=0
i_job_wait=0
if (length(taskname)==0) then i_taskname=-1
else i_taskname=0
if (length(desc)==0) then i_desc=-1
else i_desc=0
RETCD=0 ; retcd_ind=0
MSSG=LEFT(' ',1331);mssg_ind=0
return
connect_db2 :
ADDRESS TSO
"SUBCOM DSNREXX"
if rc<>0 then
S_RC = RXSUBCOM('ADD','DSNREXX','DSNREXX')
ADDRESS DSNREXX
"CONNECT" DB2_SUBSYS
If rc <> 0 Then Do
Say 'Cannot connect to ' DB2_subsys ' RC=' rc
Exit(23)
End
return
Add_task:
ADDRESS DSNREXX
'EXECSQL SET CURRENT SQLID=''"'DBADM'"'
if (sqlcode<>0) then
call sql_error
ADDRESS DSNREXX
'EXECSQL CALL :proc( ',
':uid :i_uid,',
':pwd :i_pwd,',
':begts :i_begts,',
':endts :i_endts,',
':maxinvo :i_maxinvo,',
':intval :i_intval,',
':pit :i_pit,',
':ttname :i_ttname,',
':ttcond :i_ttcond,',
':ttcode :i_ttcode,',
':dbssid :i_dbssid,',
':pschema :i_pschema,',
':pname :i_pname,',
':pinput :i_pinput,',
':jcllib :i_jcllib,',
':jclmem :i_jclmem,',
':jobwait :i_jobwait,',
':taskname :i_taskname,',
':desc :i_desc,',
':RETCD :retcd_ind,',
':MSSG :mssg_ind)'
say "Return_code= "retcd
say "Message= "mssg
if (sqlcode<>0) then
call sql_error
return
sql_error:
say sqlcode
say sqlstate
SAY SQLERRMC
SAY SQLERRP
Say 'SQLWARN = 'SQLWARN.0',' || SQLWARN.1',' || SQLWARN.2',' ||,
SQLWARN.3',' || SQLWARN.4',' || SQLWARN.5',' ||,
SQLWARN.6',' || SQLWARN.7',' || SQLWARN.8',' ||,
SQLWARN.9',' || SQLWARN.10
Say 'SQLERRD = 'SQLERRD.1',' || SQLERRD.2',' || SQLERRD.3',' ||,
SQLERRD.4',' || SQLERRD.5',' || SQLERRD.6
exit (sqlcode)
Now the code is giving error saying SQLCODE=-302.
Postion 12 of the sql call of the procedure has invalid value.
Now here pschema is at position 12 and i dont find any invalid value there.
If anybody can test out the code for me and help me in finding the error.
Back to top
dick scherrer Moderator Emeritus Joined: 23 Nov 2006Posts: 19244 Location: Inside the Matrix
Back to top
mjadwani2785 New User Joined: 28 Apr 2009Posts: 89 Location: Noida , Dublin
Quote:
Now here pschema is at position 12 and i dont find any invalid value there.
I am using here null value for pschema.. or say I am not giving any input to the field in my ispf panel where proc schema is asked and it is returning -302.
While in my other code where I am specifically hardcoding pschema=" " and calling this code from batch this is working.
I traced it compared it both seems to be same. But Still
Back to top
dick scherrer Moderator Emeritus Joined: 23 Nov 2006Posts: 19244 Location: Inside the Matrix
Hello,
Quote:
I am using here null value for pschema..
There is no such thing as a null value. . . A byte may contain any value from x'00' to x'FF' - NONE of these is a "null value".
Look at the exact valu from the batch job (in hex) and the look at the same value online (also in hex). Are they the same? If not, modify the process so that the online uses the same value that works in batch.
Back to top
mjadwani2785 New User Joined: 28 Apr 2009Posts: 89 Location: Noida , Dublin
Quote:
Look at the exact valu from the batch job (in hex) and the look at the same value online (also in hex). Are they the same?
It was quite a learning infact.
I did c2x to find out hex value for both batch and online and both are equal to 40 ?
Is there any other way to pass on null value to sql through REXX ?
Regards,
Manoj K Jadwani
Back to top
enrico-sorichetti Superior Member Joined: 14 Mar 2007Posts: 10873 Location: italy
a simple visual inspection would have show that i_job_wait is not the same as i_jobwait
Back to top
Nic Clouston Global Moderator Joined: 10 May 2007Posts: 2455 Location: Hampshire, UK
'' (no space between quotes)
Back to top
mjadwani2785 New User Joined: 28 Apr 2009Posts: 89 Location: Noida , Dublin
Thanks Enrico ..It worked...I was searching the error at pos 12.
You are always a help.
Thanks all.
Now I can proceed ahead
Back to top
Marso REXX Moderator Joined: 13 Mar 2006Posts: 1353 Location: Israel
One of the ugliest piece of code I ever saw...
Here is one of the hidden bugs:
mjadwani2785 wrote:
if (length(intval)==0) then i_intval=-1
else intval=0
Back to top
mjadwani2785 New User Joined: 28 Apr 2009Posts: 89 Location: Noida , Dublin
I accept Marso .. I m not a good coder.. actually m not from a coding backgroud . But still trying.
Your suggestions for writing good readable code will be highly appreciated.
Back to top
mjadwani2785 New User Joined: 28 Apr 2009Posts: 89 Location: Noida , Dublin
and the above bug was corrected in my original code . But still need to know how to make the code more readable .
Back to top
enrico-sorichetti Superior Member Joined: 14 Mar 2007Posts: 10873 Location: italy
start by using capitalization, proper indentation and alignment
do not try to impress people with foreign language show-off
REXX is smarter than c, no need to use the strict (==) compatrison operator
it might work, but it is always safer to put an exit statement before the procedures
Code:
Address ISPEXEC "display panel (panadm2) "
if (length(jcllib)<>0) then ,
do while(length(jclmem)=0 | length(jobwait)=0)
Address ISPEXEC "display "
end
if (rc=0) then ,
call initialise
else ,
call adieu
call connect_db2
call Add_task
call adieu
exit
adieu:
exit /*bye_bye */
initialise :
/*
upper dbssid
upper jcllib
upper jclmem
upper jobwait
upper desc
*/
DB2_SUBSYS='DB2V'
PROC = 'SYSPROC.ADMIN_TASK_ADD'
s_rc = 0
if (length(uid)=0) then i_uid=-1
else i_uid=0
if (length(pwd)=0) then i_pwd=-1
else i_pwd=0
if (length(begts)=0) then i_begts=-1
else i_begts=0
if (length(endts)=0) then i_endts=-1
else i_endts=0
if (length(maxinvo)=0) then i_maxinvo=-1
else i_maxinvo=0
if (length(intval)=0) then i_intval=-1
else intval=0
if (length(pit)=0) then i_pit=-1
else i_pit=0
if (length(ttname)=0) then i_ttname=-1
else i_ttname=0
if (length(ttcond)=0) then i_ttcond=-1
else i_ttcond=0
if (length(ttcode)=0) then i_ttcode=-1
else i_ttcode=0
if (length(dbssid)=0) then i_dbssid=-1
else i_dbssid=0
if (length(pschema)=0) then do
pschema=" "
i_pschema=-1
end
else ,
i_pschema=0
if (length(pname)=0) then i_pname=-1
else i_pname=0
if (length(pinput)=0) then i_pinput=-1
else i_pinput=0
if (length(jcllib)=0) then i_jcllib=-1
else i_jcllib=0
if (length(jclmem)=0) then i_jclmem=-1
else i_jclmem=0
i_jobwait=0
if (length(taskname)=0) then i_taskname=-1
else i_taskname=0
if (length(desc)=0) then i_desc=-1
else i_desc=0
RETCD=0
etcd_ind=0
MSSG=LEFT(' ',1331);mssg_ind=0
return
connect_db2 :
Address TSO "SUBCOM DSNREXX"
if rc<>0 then ,
S_RC = RXSUBCOM('ADD','DSNREXX','DSNREXX')
Address DSNREXX "CONNECT" DB2_SUBSYS
If rc <> 0 Then Do
Say 'Cannot connect to ' DB2_subsys ' RC=' rc
Exit(23)
End
return
Add_task:
Address DSNREXX 'EXECSQL SET CURRENT SQLID=''"'DBADM'"'
if (sqlcode<>0) then ,
call sql_error
Address DSNREXX 'EXECSQL CALL :proc( ',
':uid :i_uid,',
':pwd :i_pwd,',
':begts :i_begts,',
':endts :i_endts,',
':maxinvo :i_maxinvo,',
':intval :i_intval,',
':pit :i_pit,',
':ttname :i_ttname,',
':ttcond :i_ttcond,',
':ttcode :i_ttcode,',
':dbssid :i_dbssid,',
':pschema :i_pschema,',
':pname :i_pname,',
':pinput :i_pinput,',
':jcllib :i_jcllib,',
':jclmem :i_jclmem,',
':jobwait :i_jobwait,',
':taskname :i_taskname,',
':desc :i_desc,',
':RETCD :retcd_ind,',
':MSSG :mssg_ind)'
say "Return_code= "retcd
say "Message= "mssg
if (sqlcode<>0) then ,
call sql_error
return
sql_error:
say sqlcode
say sqlstate
SAY SQLERRMC
SAY SQLERRP
Say 'SQLWARN = 'SQLWARN.0',' || SQLWARN.1',' || SQLWARN.2',' ||,
SQLWARN.3',' || SQLWARN.4',' || SQLWARN.5',' ||,
SQLWARN.6',' || SQLWARN.7',' || SQLWARN.8',' ||,
SQLWARN.9',' || SQLWARN.10
Say 'SQLERRD = 'SQLERRD.1',' || SQLERRD.2',' || SQLERRD.3',' ||,
SQLERRD.4',' || SQLERRD.5',' || SQLERRD.6
exit (sqlcode)
REXX sometimes is too smart and makes easy to misunderstand things
for example one thing that baffles me is the implicit continuation of the if
Code:
if <logical expression> then
<some statement>
is the same as
if <logical expression> then
<some statement>
and the same as
if <logical expression> then ,
<some statement>
the first form needs two <sighting> passes
( usually the statements after an if or a do should be indented )
the second form is a bit better
my preference goes to the third form
a simple comma makes thgings much more readable
also for the simple if then else to set flags
my preference goes to
Code:
<flag> = <value for the FALSE>
if <logical expression> then ,
<flag> = <value for the TRUE>
or
<flag> = ( <logical expression > ) * <value for the TRUE>
as in
i_taskname = ( length(taskname)=0 ) * -1
it makes easier to initialize all the flags in one place and to take care of the exceptions later on
Back to top
Marso REXX Moderator Joined: 13 Mar 2006Posts: 1353 Location: Israel
Code:
address ispexec
"display panel (panadm2) "
if (length(jcllib)<>0) then
do
do while(length(jclmem)==0 | length(jobwait)==0)
address ispexec
"display "
end
end
address ispexec, when used alone on a line, permanently changes the commands destination.
(well, not exactly permanently, but until a return or exit or another address)
You must know, at given given time, to which environment you are connected.
Use address ispexec "display..." instead.
use strict operators only for strings, not numerics (unless you want to make a difference between 01 and 1 for example).
Most of the time, you don't even need strict operators.
Instead of checking for the length of a variable, you can check the variable itself:
JCLLIB = '' instead of length(JCLLIB)=0
Logical validation should be placed in the panel (using IF and VER statements)
You can check that dsnames and member names are valid, too.
Empty DO-END are just useless.
Code:
if (rc==0) then
call initialise
else
call adieu
call connect_db2
call Add_task
call adieu
Follow indentation rules!
I would connect to DB2 before displaying the panel.
If there is any problem with DB2, no need to display the panel and let the user sweat on filling all the fields,
just to send him away eventually.
Organize your calls so there are one after the other if they are always executed one after the other.
So far, here is how I would code the program:
Code:
Call connect_db2
Address ispexec "display panel (panadm2) "
If RC = 0 Then Do
Call initialise
Call Add_task
End
Exit
If you need some help about IF and VER in panels, read the books, search the forum then ask
Back to top
enrico-sorichetti Superior Member Joined: 14 Mar 2007Posts: 10873 Location: italy
Guilty as charged, I forgot to tell to check the return code..
Return code checking is mandatory after the invocation of any foreign service
it comes so natural that i forget to tell
and if the cleanup code is short I prefer often the other way around
Address ISPEXEC "display panel (panadm2) "
if RC \= 0 then do
<clenup and terminate >
end
but my true preference goes to strict structured programming,
thats why I alway use wrappers around ISPF and TSO environments
so that I can code ...
Code:
Do while ( $ispex("DISPLAY PANEL(MYPANEL)" = 0 )
< normal processing >
end
....
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
$tsoex:
tso_0tr = trace("O")
Address TSO arg(1)
tso_0rc = rc
trace value(tso_0tr)
return tso_0rc
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
$ispex:
isp_tr = trace("O")
Address ISPEXEC arg(1)
isp_rc = rc
trace value(isp_tr)
return isp_rc
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
$isred:
isr_tr = trace("O")
Address ISREDIT arg(1)
isr_rc = rc
trace value(isr_tr)
return isr_rc
Back to top
Marso REXX Moderator Joined: 13 Mar 2006Posts: 1353 Location: Israel
Code:
i_taskname = ( length(taskname)=0 ) * -1
That was supposed to be the second part of my post!
It works because
Quote:
The comparison operators compare two terms and return the value 1 if the result of the comparison is true, or 0 otherwise.
Coding
Code:
i_uid = ( length(uid)=0 ) * -1
i_pwd = ( length(pwd)=0 ) * -1
i_begts = ( length(begts)=0 ) * -1
i_endts = ( length(endts)=0 ) * -1
i_maxinvo = ( length(maxinvo)=0 ) * -1
i_intval = ( length(intval)=0 ) * -1
or
Code:
i_uid = ( uid='' ) * -1
i_pwd = ( pwd='' ) * -1
i_begts = ( begts='' ) * -1
i_endts = ( endts='' ) * -1
i_maxinvo = ( maxinvo='' ) * -1
i_intval = ( intval='' ) * -1
makes the code much easier to read...
And less bugged...
Code:
Address DSNREXX 'EXECSQL SET CURRENT SQLID=''"'DBADM'"'
There are too many quotes. It is now difficult to understand if DBADM is a variable or the value.
Code:
Address DSNREXX 'EXECSQL SET CURRENT SQLID="'DBADM'"' /*variable*/
Address DSNREXX 'EXECSQL SET CURRENT SQLID="DBADM"' /*value*/
Back to top
enrico-sorichetti Superior Member Joined: 14 Mar 2007Posts: 10873 Location: italy
Quote:
There are too many quotes. It is now difficult to understand if DBADM is a variable or the value.
that' s one of the reasons that for strings I prefer to use <"> rather than <'>
and I just did not feel to interpret the quotes/apostr mess
Back to top
Please enable JavaScript!