# Usage: the standard syntax: # WITH RECURSIVE recursive_table AS # (initial_SELECT # UNION ALL # recursive_SELECT) # final_SELECT; # should be translated by you to # CALL WITH_EMULATOR(recursive_table, initial_SELECT, recursive_SELECT, # final_SELECT, 0, ""). # ALGORITHM: # 1) we have an initial table T0 (actual name is an argument # "recursive_table"), we fill it with result of initial_SELECT. # 2) We have a union table U, initially empty. # 3) Loop: # add rows of T0 to U, # run recursive_SELECT based on T0 and put result into table T1, # if T1 is empty # then leave loop, # else swap T0 and T1 (renaming) and empty T1 # 4) Drop T0, T1 # 5) Rename U to T0 # 6) run final select, send result to client # This is for *one* recursive table. # It would be possible to write a SP creating multiple recursive tables. delimiter | CREATE PROCEDURE WITH_EMULATOR( recursive_table varchar(100), initial_SELECT varchar(65530), recursive_SELECT varchar(65530), final_SELECT varchar(65530), max_recursion int unsigned, create_table_options varchar(65530) ) BEGIN declare new_rows int unsigned; declare show_progress int default 0; declare recursive_table_next varchar(120); declare recursive_table_union varchar(120); declare recursive_table_tmp varchar(120); set recursive_table_next = concat(recursive_table, "_next"); set recursive_table_union = concat(recursive_table, "_union"); set recursive_table_tmp = concat(recursive_table, "_tmp"); SET @str = CONCAT("CREATE TEMPORARY TABLE ", recursive_table, " ", create_table_options, " AS ", initial_SELECT); PREPARE stmt FROM @str; EXECUTE stmt; SET @str = CONCAT("CREATE TEMPORARY TABLE ", recursive_table_union, " LIKE ", recursive_table); PREPARE stmt FROM @str; EXECUTE stmt; SET @str = CONCAT("CREATE TEMPORARY TABLE ", recursive_table_next, " LIKE ", recursive_table); PREPARE stmt FROM @str; EXECUTE stmt; if max_recursion = 0 then set max_recursion = 100; end if; recursion: repeat SET @str = CONCAT("INSERT INTO ", recursive_table_union, " SELECT * FROM ", recursive_table); PREPARE stmt FROM @str; EXECUTE stmt; set max_recursion = max_recursion - 1; if not max_recursion then if show_progress then select concat("max recursion exceeded"); end if; leave recursion; end if; SET @str = CONCAT("INSERT INTO ", recursive_table_next, " ", recursive_SELECT); PREPARE stmt FROM @str; EXECUTE stmt; select row_count() into new_rows; if show_progress then select concat(new_rows, " new rows found"); end if; if not new_rows then leave recursion; end if; SET @str = CONCAT("ALTER TABLE ", recursive_table, " RENAME ", recursive_table_tmp); PREPARE stmt FROM @str; EXECUTE stmt; SET @str = CONCAT("ALTER TABLE ", recursive_table_next, " RENAME ", recursive_table); PREPARE stmt FROM @str; EXECUTE stmt; SET @str = CONCAT("ALTER TABLE ", recursive_table_tmp, " RENAME ", recursive_table_next); PREPARE stmt FROM @str; EXECUTE stmt; SET @str = CONCAT("TRUNCATE TABLE ", recursive_table_next); PREPARE stmt FROM @str; EXECUTE stmt; until 0 end repeat; SET @str = CONCAT("DROP TEMPORARY TABLE ", recursive_table_next, ", ", recursive_table); PREPARE stmt FROM @str; EXECUTE stmt; SET @str = CONCAT("ALTER TABLE ", recursive_table_union, " RENAME ", recursive_table); PREPARE stmt FROM @str; EXECUTE stmt; SET @str = final_SELECT; PREPARE stmt FROM @str; EXECUTE stmt; SET @str = CONCAT("DROP TEMPORARY TABLE ", recursive_table); PREPARE stmt FROM @str; EXECUTE stmt; END| delimiter ;