From: asceta on
I was wondering, whether it is possible to create recursive SQL PL
functions in DB2. A simple example:

CREATE OR REPLACE FUNCTION fibo (
k integer
)
RETURNS integer
BEGIN
IF k < 2 THEN
return 1;
ELSE
return fibo(k-1) + fibo(k-2);
END IF;
END !

ends up with rather unexpected error:

DB21034E The command was processed as an SQL statement because it was
not a
valid Command Line Processor command. During SQL processing it
returned:
SQL20481N The creation or revalidation of object xxxxxx
would result in an invalid direct or indirect self-reference. LINE
NUMBER=11.
SQLSTATE=429C3

I use DB2 9.7 Express

Anyone can help me solve that issue ?
From: Lennart on
On 31 mar, 20:17, asceta <marek.patr...(a)gmail.com> wrote:
> I was wondering, whether it is possible to create recursive SQL PL
> functions in DB2. A simple example:
>
> CREATE OR REPLACE FUNCTION fibo (
>     k integer
> )
> RETURNS integer
> BEGIN
>     IF k < 2 THEN
>         return 1;
>     ELSE
>         return fibo(k-1) + fibo(k-2);
>     END IF;
> END !
>
> ends up with rather unexpected error:
>
> DB21034E  The command was processed as an SQL statement because it was
> not a
> valid Command Line Processor command.  During SQL processing it
> returned:
> SQL20481N  The creation or revalidation of object xxxxxx
> would result in an invalid direct or indirect self-reference.  LINE
> NUMBER=11.
> SQLSTATE=429C3
>
> I use DB2 9.7 Express
>
> Anyone can help me solve that issue ?

I don't think you can have the function call itself (I don't have
access to 9.7 so I haven't tried, but that seems to be what the error
message says). One option is to use a recursive cte in the function.
In your case:

create function fibo (k int)
returns bigint
return
with next (i, j, n) as (
values (bigint(0), bigint(1), k)
union all
select j, i+j, n-1 from next where n>1
)
select max(j) from next
@

[... ~]$ time db2 "values fibo(92)"

1
--------------------
7540113804746346429

1 record(s) selected.


real 0m0.046s
user 0m0.011s
sys 0m0.021s


There are restrictions on what kind of recursion you are allowed to in
a cte as well (I'm not entirely clear of what they are though). As an
example you can't do ackerman because it involves nested recursive
calls.

/Lennart
From: Serge Rielau on
> Anyone can help me solve that issue ?
You can use dynamic SQL for the recursive part.
So do a dynamic 'SET ? = ..'
and then return the result of that.
Note that DB2 imposed a limit of 64 levels on nesting.


--
Serge Rielau
SQL Architect DB2 for LUW
IBM Toronto Lab

From: Lennart on
On 31 mar, 20:17, asceta <marek.patr...(a)gmail.com> wrote:
> I was wondering, whether it is possible to create recursive SQL PL
> functions in DB2. A simple example:
>
> CREATE OR REPLACE FUNCTION fibo (
>     k integer
> )
> RETURNS integer
> BEGIN
>     IF k < 2 THEN
>         return 1;
>     ELSE
>         return fibo(k-1) + fibo(k-2);
>     END IF;
> END !
>
> ends up with rather unexpected error:
>
> DB21034E  The command was processed as an SQL statement because it was
> not a
> valid Command Line Processor command.  During SQL processing it
> returned:
> SQL20481N  The creation or revalidation of object xxxxxx
> would result in an invalid direct or indirect self-reference.  LINE
> NUMBER=11.
> SQLSTATE=429C3
>
> I use DB2 9.7 Express
>
> Anyone can help me solve that issue ?

I've got a private mail from a person that pointed out that in 9.7
there is a new concept, module. Since I don't have a 9.7 installation
yet, I haven't checked it out. From his description it looks as if you
can forward declare a function (pretty much the same way as you do
with a header file). Anyhow, here's his example:

CREATE MODULE M@

ALTER MODULE M PUBLISH FUNCTION FIBO ( K INTEGER ) RETURNS INTEGER@

ALTER MODULE M ADD FUNCTION FIBO ( K INTEGER )
RETURNS INTEGER
BEGIN
IF K < 2 THEN
RETURN 1;
ELSE
RETURN FIBO(K-1) + FIBO(K-2);
END IF;
END@

VALUES(M.FIBO(25))

1
-----------
121393

1 record(s) selected.


I'm curious, is it possible to define for example:

CREATE MODULE X@

ALTER MODULE X PUBLISH FUNCTION ACK ( i INT, j INT ) RETURNS INT@

ALTER MODULE X ADD FUNCTION ACK ( i INT, j INT )
RETURNS INT
BEGIN
IF i = 0 THEN
RETURN j+1;
ELSE IF j = 0 THEN
RETURN ACC(i-1, 1);
ELSE
RETURN ACC(i-1, ACC(i,j-1));
END IF;
END@

VALUES(X.ACC(3,6)) @

Anyone with a working 9.7 install that is willing to try?

/Lennart

From: Lennart on
On 1 Apr, 21:03, Lennart <erik.lennart.jons...(a)gmail.com> wrote:
> On 31 mar, 20:17, asceta <marek.patr...(a)gmail.com> wrote:
>
>
>
> > I was wondering, whether it is possible to create recursive SQL PL
> > functions in DB2. A simple example:
>
> > CREATE OR REPLACE FUNCTION fibo (
> >     k integer
> > )
> > RETURNS integer
> > BEGIN
> >     IF k < 2 THEN
> >         return 1;
> >     ELSE
> >         return fibo(k-1) + fibo(k-2);
> >     END IF;
> > END !
>
> > ends up with rather unexpected error:
>
> > DB21034E  The command was processed as an SQL statement because it was
> > not a
> > valid Command Line Processor command.  During SQL processing it
> > returned:
> > SQL20481N  The creation or revalidation of object xxxxxx
> > would result in an invalid direct or indirect self-reference.  LINE
> > NUMBER=11.
> > SQLSTATE=429C3
>
> > I use DB2 9.7 Express
>
> > Anyone can help me solve that issue ?
>
> I've got a private mail from a person that pointed out that in 9.7
> there is a new concept, module. Since I don't have a 9.7 installation
> yet, I haven't checked it out. From his description it looks as if you
> can forward declare a function (pretty much the same way as you do
> with a header file). Anyhow, here's his example:
>
> CREATE MODULE M@
>
> ALTER MODULE M PUBLISH FUNCTION FIBO ( K INTEGER ) RETURNS INTEGER@
>
> ALTER MODULE M ADD FUNCTION FIBO ( K INTEGER )
>   RETURNS INTEGER
> BEGIN
>    IF K < 2 THEN
>       RETURN 1;
>    ELSE
>       RETURN FIBO(K-1) + FIBO(K-2);
>    END IF;
> END@
>
> VALUES(M.FIBO(25))
>
> 1
> -----------
>      121393
>
>   1 record(s) selected.
>
> I'm curious, is it possible to define for example:
>
> CREATE MODULE X@
>
> ALTER MODULE X PUBLISH FUNCTION ACK ( i INT, j INT ) RETURNS INT@
>
> ALTER MODULE X ADD FUNCTION ACK ( i INT, j INT )
>   RETURNS INT
> BEGIN
>    IF i = 0 THEN
>       RETURN j+1;
>    ELSE IF j = 0 THEN
>       RETURN ACC(i-1, 1);
>    ELSE
>       RETURN ACC(i-1, ACC(i,j-1));
>    END IF;
> END@
>
> VALUES(X.ACC(3,6)) @
>
> Anyone with a working 9.7 install that is willing to try?
>
> /Lennart

Sorry, make that:

CREATE MODULE X@
ALTER MODULE X PUBLISH FUNCTION ACK ( i INT, j INT ) RETURNS INT@

ALTER MODULE X ADD FUNCTION ACK ( i INT, j INT )
RETURNS INT
BEGIN
IF i = 0 THEN
RETURN j+1;
ELSE IF j = 0 THEN
RETURN ACK(i-1, 1);
ELSE
RETURN ACK(i-1, ACC(i,j-1));
END IF;
END@

VALUES(X.ACK(3,6)) @

/Lennart
 |  Next  |  Last
Pages: 1 2
Prev: strange query behaviour
Next: COUNT(*) Not accurate?