6

I've written a stored FUNCTION that calls itself, recursively.

However when I run it in a query I get this shameless error:

Error: 1424 SQLSTATE: HY000 (ER_SP_NO_RECURSION)

Message: Recursive stored functions and triggers are not allowed.

"Not allowed"?
Right. Why don't we just disable WHILE loops also, while we're at it?

Can I enable recursive functions in any way?
I found a bug report, but are there any workarounds?
I'm running MySQL 5.1.41 on Windows XP (XAMPP Server).

Community
  • 1
  • 1
Robin Rodricks
  • 110,798
  • 141
  • 398
  • 607
  • 2
    A database is for retrieving data, not for programming. Is there some reason you're trying to do complex, difficult-to-predict-or-optimize logic in a stored procedure instead of in your application? – Borealid Aug 21 '10 at 06:00
  • http://stackoverflow.com/questions/3438111/mysql-stored-procedure-that-calles-itself-recursively – Novemberland Aug 21 '10 at 06:05
  • 1
    A shameless error! There is a way you can enable recursive functions; you have to modify the MySQL code to make them work. – Brian Hooper Aug 21 '10 at 06:36
  • Which MySQL code? Don't ask me to make a custom build of MySQL Server. – Robin Rodricks Aug 21 '10 at 06:40

3 Answers3

4

MySQL 5.1 supports recursive stored procedures, but not recursive functions. Quoting the docs:

Stored functions cannot be recursive.

Recursion in stored procedures is permitted but disabled by default. To enable recursion, set the max_sp_recursion_depth server system variable to a value greater than zero. Stored procedure recursion increases the demand on thread stack space. If you increase the value of max_sp_recursion_depth, it may be necessary to increase thread stack size by increasing the value of thread_stack at server startup.

Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
  • I would still like a solution using FUNCTIONS because I have a recursive method that calls itself expecting return values. If I used a PROCEDURE there's no way I'll be able to do that... would I? – Robin Rodricks Aug 21 '10 at 08:04
  • 1
    @Jenko: Anything that can be done using recursion can be rewritten using iteration: http://stackoverflow.com/questions/931762/can-every-recursion-be-converted-into-iteration – Daniel Vassallo Aug 21 '10 at 08:09
3

Probably recursion in stored routines is discouraged because MySQL needs to limit its threads' stack size.

MySQL typically uses one thread per connection. 100s or 1000s of connections are common.

On 32-bit platforms, there is significant address-space pressure when running 1,000 threads, so the stacks need to be set very small to avoid address-space exhaustion.

Stack overflow is, of course, very bad - it can't be recovered from safely. So I think MySQL does this to prevent stack overflows, especially on 32-bit platforms.

That said, anyone using a 32-bit OS for a production MySQL server nowadays is insane.

MarkR
  • 62,604
  • 14
  • 116
  • 151
  • "Stack overflow is, of course, very bad - it can't be recovered from safely" this is outright wrong. ALL reasonable higher-level programming languages manage to recover safely from stack overflows, such as Java, Perl, Python, ... – intgr Jan 07 '11 at 08:38
3

No problem, Jenco. Not so efficient as PostgreSQL functions, but it's possible in MySQL procedures also:

DELIMITER $$
DROP PROCEDURE IF EXISTS test.factorial_proc$$
CREATE PROCEDURE test.factorial_proc
(
   IN n   BIGINT, 
  OUT res BIGINT 
) 
BEGIN
  SET max_sp_recursion_depth=10; 
  IF n >= 2 THEN
    CALL test.factorial_proc (n-1, res);
    SELECT n * res INTO res;
  ELSE
    SELECT n INTO res;
  END IF;
END$$
DELIMITER ;

[test]> CALL test.factorial_proc (5, @res);
[test]> CALL test.factorial_proc (5, @res1);
[test]> select @res * @res1;
+--------------+
| @res * @res1 |
+--------------+
|        14400 |
+--------------+

Sergei Zaytsev.

Robin Rodricks
  • 110,798
  • 141
  • 398
  • 607