greasedman
13th January 2005, 14:52
I read treads about recursion, so I know that it shoud be possible in BaaN IV, but with some problems for queries; however, I still don't know how to fix'em and if it's allowed.
My case is something like the following one:


function a()
{
select f
from f
selectempty
b()
endselect
}

function b()
{
select c
from c
selectdo
a()
endselect

d = e
}



As example I can say that the select on "c" should give me 2 rows, but when it returns from the first recursion turn, instead of start the second turn it jumps directly to the final statements (d = e), and shows a BW message like: "Select should be in exec staus or eval status".

There are REALLY no way to perform recursion in a way like that one?!?

malutz
13th January 2005, 16:16
I once programmed a recursion in BaanV as well, but sadly when compiling I got the error message:

Recursion not yet implemented.

greasedman
13th January 2005, 16:29
read this http://www.baanboard.com/baanboard/showthread.php?t=1315&highlight=recursion+static
it should be useful for you. It was for me!

chjagge
13th January 2005, 22:14
this is actual code from one of my sessions. I found the basic template in this forum. Generate a sesison on tipcf310. then cut and paste the code below compile and run.

|******************************************************************************
|* Main table tipcf310 Generic BOMs, Form Type 4
|******************************************************************************

|****************************** declaration section ***************************
declaration:

table ttipcf310 | Generic BOMs
table ttiitm001 | Items


extern domain tcitem mitm.f fixed
domain tcitem mitm.w
extern domain tcpono pono.f
extern domain tcpono pono.t
extern domain tcsern sern.f
extern domain tcsern sern.t
extern long level.recursion,sql.x,sql(199)

|****************************** form section **********************************

form.1:
init.form:
get.screen.defaults()

|****************************** choice section ********************************

choice.cont.process:
on.choice:
execute(print.data)

choice.print.data:
on.choice:
if rprt_open() then
level.recursion = 0
read.main.table()
rprt_close()
else
choice.again()
endif


|****************************** field section *********************************

field.mitm.f:
before.zoom:
tiitm001.item = mitm.f

field.pono.f:
when.field.changes:
pono.t = pono.f

field.sern.f:
when.field.changes:
sern.t = sern.f


|****************************** function section ******************************

functions:

function read.main.table()
{
level.recursion = level.recursion + 1
sql.x=sql.parse("select tipcf310.* " &
"from tipcf310 " &
"where tipcf310._index1 = {:1}")
sql.where.bind(sql.x,1,mitm.f)
sql(level.recursion)=sql.x
sql.exec(sql.x)
while (sql.fetch(sql.x) = 0)
rprt_send()
mitm.f = tipcf310.sitm
mitm.w = tipcf310.mitm
read.main.table()
endwhile
sql.close(sql.x)
level.recursion = level.recursion - 1
if level.recursion <> 0 then
sql.x=sql(level.recursion)
endif
}

greasedman
17th January 2005, 16:51
this is actual code from one of my sessions. I found the basic template in this forum. Generate a sesison on tipcf310. then cut and paste the code below compile and run.

|******************************************************************************
|* Main table tipcf310 Generic BOMs, Form Type 4
|******************************************************************************

|****************************** declaration section ***************************
declaration:

table ttipcf310 | Generic BOMs
table ttiitm001 | Items


extern domain tcitem mitm.f fixed
domain tcitem mitm.w
extern domain tcpono pono.f
extern domain tcpono pono.t
extern domain tcsern sern.f
extern domain tcsern sern.t
extern long level.recursion,sql.x,sql(199)

|****************************** form section **********************************

form.1:
init.form:
get.screen.defaults()

|****************************** choice section ********************************

choice.cont.process:
on.choice:
execute(print.data)

choice.print.data:
on.choice:
if rprt_open() then
level.recursion = 0
read.main.table()
rprt_close()
else
choice.again()
endif


|****************************** field section *********************************

field.mitm.f:
before.zoom:
tiitm001.item = mitm.f

field.pono.f:
when.field.changes:
pono.t = pono.f

field.sern.f:
when.field.changes:
sern.t = sern.f


|****************************** function section ******************************

functions:

function read.main.table()
{
level.recursion = level.recursion + 1
sql.x=sql.parse("select tipcf310.* " &
"from tipcf310 " &
"where tipcf310._index1 = {:1}")
sql.where.bind(sql.x,1,mitm.f)
sql(level.recursion)=sql.x
sql.exec(sql.x)
while (sql.fetch(sql.x) = 0)
rprt_send()
mitm.f = tipcf310.sitm
mitm.w = tipcf310.mitm
read.main.table()
endwhile
sql.close(sql.x)
level.recursion = level.recursion - 1
if level.recursion <> 0 then
sql.x=sql(level.recursion)
endif
}


Thanks, it should work!!!

But are you sure I haven't to use "static" declaration for variables like level.recursion, sql.x, and so on...?

chjagge
17th January 2005, 17:34
This is actual code in production. Its works as is.

chjagge
21st January 2005, 18:38
Crossed function recursion works also. Below is a report that drills down tipcf310 & tibom010 and pulls out the multi-level far more elgantly than the vanilla session tipcf3411m000. Although this is specific to our user requirement here the basic concept can be reused.
Actual code used in production.


|******************************************************************************
|* tipcft414 0 VRC B40O c2 bta0
|* Print Generic BOMs - recursive
|* Christopher Jaggernauth
|* 2005-01-05
|******************************************************************************
|******************************************************************************
|* Main table tipcf310 Generic BOMs, Form Type 4
|******************************************************************************

|****************************** declaration section ***************************
declaration:

table ttipcf310 | Generic BOMs
table ttibom010 | Production BOM
table ttipcf320 | Generic Routings
table ttiitm001 | Items
table ttirou102 | Routing


extern domain tcitem mitm.f fixed | screen
extern domain tcitem mitm.save
extern domain tcitem mitm.w | report
extern domain tcitem sitm.w | report
extern domain tcpono pono.f | screen
extern domain tcpono pono.t | screen
extern domain tcpono pono.w | report
extern domain tcsern sern.f | screen
extern domain tcsern sern.t | screen
extern domain tcsern sern.w | report
extern long level.recursion,sql.x,sql(199)
extern domain tcrutm rutm.w | report
extern domain tccwoc cwoc.w | report
extern domain tiqbm2 qana.w | report
domain tcdate eff.date
domain tcbool has.data

|****************************** form section **********************************

form.1:
init.form:
get.screen.defaults()

|****************************** choice section ********************************

choice.cont.process:
on.choice:
execute(print.data)

choice.print.data:
on.choice:
if rprt_open() then
mitm.save = mitm.f
level.recursion = 0
read.main.table.generic()
mitm.f = mitm.save
send.top.level.generic()
display("mitm.f")
refresh()
rprt_close()
else
choice.again()
endif


|****************************** field section *********************************
field.pono.f:
when.field.changes:
pono.t = pono.f

field.sern.f:
when.field.changes:
sern.t = sern.f


|****************************** function section ******************************

functions:

function send.top.level.generic()
{
select tiitm001.*
from tiitm001
where tiitm001._index1 = {:mitm.f}
selectdo
if (print.item(tiitm001.item))then
mitm.w = tiitm001.item
pono.w = 0
sern.w = 0
sitm.w = tiitm001.item
qana.w = 1
get.extra.info(tiitm001.item)
endif
endselect

}
function read.main.table.production()
{
eff.date = date.num()
level.recursion = level.recursion + 1
sql.x=sql.parse("select tibom010.mitm, tibom010.pono " &
"from tibom010 " &
"where tibom010._index1 = {:1} " &
"group by tibom010.mitm, tibom010.pono")
sql.where.bind(sql.x,1,mitm.f)
sql(level.recursion)=sql.x
sql.exec(sql.x)
while (sql.fetch(sql.x) = 0)
has.data = true
select a.sitm:mitm.f, a.sitm:tibom010.sitm, a.qana:tibom010.qana,
a.indt:tibom010.indt, a.exdt:tibom010.exdt, a.seqn:tibom010.seqn
from tibom010 a
where a._index1 = {:tibom010.mitm, :tibom010.pono}
and ((a.indt <= :eff.date) and (:eff.date < a.exdt or a.exdt = 0))
as set with 1 rows
selectdo
| if ((tibom010.indt <= eff.date) and (eff.date < tibom010.exdt or tibom010.exdt = 0)) then
| break
| endif
|*** Since using the as set wit 1 rows the if-then statement is not needed
selectempty
has.data = false
endselect
if (print.item(tibom010.sitm) and (not is.expired(tibom010.indt, tibom010.exdt)) and has.data) then
mitm.w = tibom010.mitm
pono.w = tibom010.pono
sern.w = tibom010.seqn
sitm.w = tibom010.sitm
qana.w = tibom010.qana
get.extra.info(tibom010.sitm)
endif
if ((not is.purchased(tibom010.sitm)) and (not is.expired(tibom010.indt, tibom010.exdt)) and has.data) then
if ((tiitm001.kitm = tckitm.generic) or (tiitm001.kitm = tckitm.manufacture)) then
if (tiitm001.kitm = tckitm.generic) then
read.main.table.generic()
else
read.main.table.production()
endif
endif
endif
endwhile
sql.close(sql.x)
level.recursion = level.recursion - 1
if level.recursion <> 0 then
sql.x=sql(level.recursion)
endif
}


function read.main.table.generic()
{
eff.date = date.num()
level.recursion = level.recursion + 1
sql.x=sql.parse("select tipcf310.mitm, tipcf310.pono " &
"from tipcf310 " &
"where tipcf310._index1 = {:1} " &
"group by tipcf310.mitm, tipcf310.pono")
sql.where.bind(sql.x,1,mitm.f)
sql(level.recursion)=sql.x
sql.exec(sql.x)
while (sql.fetch(sql.x) = 0)
has.data = true
select a.sitm:mitm.f, a.sitm:tipcf310.sitm, a.qana:tipcf310.qana,
a.indt:tipcf310.indt, a.exdt:tipcf310.exdt, a.sern:tipcf310.sern
from tipcf310 a
where a._index1 = {:tipcf310.mitm, :tipcf310.pono}
and ((a.indt <= :eff.date) and (:eff.date < a.exdt or a.exdt = 0))
as set with 1 rows
selectdo
| if ((tipcf310.indt <= eff.date) and (eff.date < tipcf310.exdt or tipcf310.exdt = 0)) then
| break
| endif
|*** Since using the as set wit 1 rows the if-then statement is not needed
selectempty
has.data = false
endselect
if (print.item(tipcf310.sitm) and (not is.expired(tipcf310.indt, tipcf310.exdt)) and has.data) then
mitm.w = tipcf310.mitm
pono.w = tipcf310.pono
sern.w = tipcf310.sern
sitm.w = tipcf310.sitm
qana.w = tipcf310.qana
get.extra.info(tipcf310.sitm)
endif
if ((not is.purchased(tipcf310.sitm)) and (not is.expired(tipcf310.indt,tipcf310.exdt)) and has.data) then
if ((tiitm001.kitm = tckitm.generic) or (tiitm001.kitm = tckitm.manufacture)) then
if (tiitm001.kitm = tckitm.generic) then
read.main.table.generic()
else
read.main.table.production()
endif
endif
endif
endwhile
sql.close(sql.x)
level.recursion = level.recursion - 1
if level.recursion <> 0 then
sql.x=sql(level.recursion)
endif
}


function get.extra.info(domain tcitem sitm.x)
{
if tiitm001.kitm = tckitm.manufacture then
select tirou102.mitm, tirou102.opro, tirou102.opno
from tirou102
where tirou102._index1 = {:sitm.x}
group by tirou102.mitm, tirou102.opro, tirou102.opno
selectdo
select b.cwoc:cwoc.w, b.rutm:rutm.w, b.indt, b.exdt
from tirou102 b
where b._index1 = {:tirou102.mitm, :tirou102.opro, :tirou102.opno}
and ((b.indt <= :eff.date) and (:eff.date < b.exdt or b.exdt = 0))
and b.cwoc <> "900" and b.cwoc <> "998"
as set with 1 rows
selectdo
rprt_send()
endselect
endselect
else
select tipcf320.mitm, tipcf320.opno
from tipcf320
where tipcf320._index1 = {:sitm.x}
group by tipcf320.mitm, tipcf320.opno
selectdo
select b.cwoc:cwoc.w, b.rutm:rutm.w, b.indt, b.exdt
from tipcf320 b
where b._index1 = {:tipcf320.mitm, :tipcf320.opno}
and ((b.indt <= :eff.date) and (:eff.date < b.exdt or b.exdt = 0))
and b.cwoc <> "900" and b.cwoc <> "998"
as set with 1 rows
selectdo
rprt_send()
endselect
endselect
endif
}

function domain tcbool print.item(domain tcitem sitm.x)
{
select tiitm001.*
from tiitm001
where tiitm001._index1 = {:sitm.x}
and tiitm001.kitm > tckitm.purchase
and tiitm001.kitm < tckitm.cost
and tiitm001.cpha = tcyesno.no
selectdo
return(true)
endselect
return (false)
}

function domain tcbool is.purchased(domain tcitem sitm.x)
{
select tiitm001.*
from tiitm001
where tiitm001._index1 = {:sitm.x}
selectdo
if (tiitm001.kitm = tckitm.purchase) then
return(true)
else
return(false)
endif
endselect
return(false)
}

function domain tcbool is.expired(domain tcdate indt.x, domain tcdate exdt.x)
{
if ((indt.x <= eff.date) and (eff.date < exdt.x or exdt.x = 0)) then
return(false)
else
return(true)
endif
}

greasedman
24th January 2005, 13:55
Crossed function recursion works also. Below is a report that drills down tipcf310 & tibom010 and pulls out the multi-level far more elgantly than the vanilla session tipcf3411m000. Although this is specific to our user requirement here the basic concept can be reused.
Actual code used in production.
Nice, it works!!!
Thanks u all, really useful help!!!
:)

addecker
16th October 2007, 12:32
Hey guys,
by making your sql-pointer (in this case sql.x) a local static variable for function read.main.table, you do not need to maintain an array of sql pointers nor the level of recursion you are in.

Alain De Decker