(
IN p_ProgramID INTEGER,
IN p_ForwardOrBackward SMALLINT
)
DYNAMIC RESULT SETS 1
LANGUAGE SQL
ss: BEGIN

        DECLARE SQLSTATE CHAR(5) DEFAULT '00000';
        DECLARE SQLCODE INTEGER DEFAULT 0;
        DECLARE v_ERRORMSG VARCHAR(4000) DEFAULT '';


         -- clean up temp table if exists
		BEGIN
			DECLARE CONTINUE HANDLER FOR SQLSTATE '42704'
			BEGIN END;
			
			COMMIT;
			DROP TABLE SESSION.x;
			DROP TABLE SESSION.fin;
		END;


        BEGIN

            DECLARE v_ProgramID ,v_rc ,v_i ,v_j INTEGER;
            DECLARE v_ForwardOrBackward  SMALLINT DEFAULT 1; /* 1 Forward  and  -1 Backward ; forward forced*/

            DECLARE real_issue CONDITION FOR SQLSTATE '80010';
			DECLARE EXIT HANDLER FOR SQLEXCEPTION RESIGNAL;

            DECLARE GLOBAL TEMPORARY TABLE SESSION.x
			(
			   FromProgramID INTEGER
			  ,ToProgramID INTEGER
			) ON COMMIT PRESERVE ROWS
			   NOT LOGGED;
			
			
			DECLARE GLOBAL TEMPORARY TABLE SESSION.fin
			(
                  FromProgramID  INTEGER
                 ,ToProgramID    INTEGER
                 --,Calling_Concat VARCHAR(32000)
                 --,Lvl            INTEGER
			) ON COMMIT PRESERVE ROWS
			     NOT LOGGED;



            SET v_ProgramID = COALESCE(p_ProgramID, 0);
            SET v_ForwardOrBackward = COALESCE(p_ForwardOrBackward, 1 ); -- DEFAULT IS FORWARD


            IF(v_ForwardOrBackward NOT IN (1, -1))
            THEN
                  SET v_ERRORMSG = 'Please use corect ForwardOrBackward: 1 -> FORWARD  or  -1 -> BACKWARD' ;

                  SIGNAL real_issue
				  SET MESSAGE_TEXT = v_ERRORMSG;
				
				   RETURN ;	
            END IF;


       	    INSERT INTO SESSION.x (FromProgramID, ToProgramID)
			SELECT os.ProgID, sr.ResourceID
			FROM StatementReference sr
				INNER JOIN OccurrencesStmt os ON sr.OccurID = os.OccurID
			WHERE sr.ResourceType = 5
			GROUP BY os.ProgID, sr.ResourceID ;

										
            CREATE UNIQUE INDEX unqidx1 ON SESSION.x (FromProgramID, ToProgramID);	
            CREATE UNIQUE INDEX unqidx2 ON SESSION.x (ToProgramID ,FromProgramID);	



           	-- GET LEVEL 0
			INSERT INTO SESSION.fin (FromProgramID, ToProgramID /*,Calling_Concat ,Lvl*/)
			SELECT x.FromProgramID, x.ToProgramID
			       --,'#' || CAST( (CASE v_ForwardOrBackward WHEN 1 THEN x.FromProgramID ELSE x.ToProgramID   END) AS VARCHAR(50)) ||
			       -- '#' || CAST( (CASE v_ForwardOrBackward WHEN 1 THEN x.ToProgramID   ELSE x.FromProgramID END) AS VARCHAR(50)) AS Calling_Concat
			       --, 0 AS Lvl
			FROM SESSION.x x
			WHERE v_ProgramID = CASE v_ForwardOrBackward WHEN 1 THEN x.FromProgramID ELSE x.ToProgramID END ;


            -- IMBRICATIONS LEVELES  1-> 2000 (2000 levels of imbrication)
            SET v_i = 1 ;
		    SET v_j = 2001 ;

             -- GET NEXT LEVELS VALUES
			WHILE ( v_i < v_j )
			DO
                        SET v_rc = 0 ;

                        IF (v_ForwardOrBackward = 1)
						THEN
							

									INSERT INTO SESSION.fin(FromProgramID ,ToProgramID /*,Calling_Concat ,Lvl*/)
									SELECT f1.FromProgramID, x.ToProgramID
										  --,f1.Calling_Concat  || '#' || CAST(x.ToProgramID AS VARCHAR(50)),  f1.Lvl + 1
									FROM SESSION.x x
											INNER JOIN SESSION.fin f1 ON f1.ToProgramID = x.FromProgramID
											LEFT OUTER JOIN SESSION.fin f2 ON f1.FromProgramID = f2.FromProgramID
																AND x.ToProgramID = f2.ToProgramID
									WHERE  f2.FromProgramID IS NULL ;

                                    GET DIAGNOSTICS v_rc = ROW_COUNT;								
							
						ELSE
							
							           INSERT INTO SESSION.fin(FromProgramID ,ToProgramID /*,Calling_Concat ,Lvl*/)
									   SELECT  x.FromProgramID, f1.ToProgramID
											  -- ,f1.Calling_Concat  || '#' || CAST(x.FromProgramID AS VARCHAR(50)),  f1.Lvl + 1
										FROM SESSION.x x
												INNER JOIN SESSION.fin f1 ON x.ToProgramID = f1.FromProgramID
												LEFT OUTER JOIN SESSION.fin f2 ON f1.ToProgramID = f2.ToProgramID
																	AND x.FromProgramID = f2.FromProgramID
										WHERE  f2.ToProgramID IS NULL ;

										GET DIAGNOSTICS v_rc = ROW_COUNT;

						END IF;	


						IF COALESCE(v_rc, 0) = 0
						   THEN  SET v_i = v_j ;
						   ELSE  SET v_i = v_i + 1 ;
						END IF;
						
			END WHILE ;




           BEGIN
	
	                DECLARE crs CURSOR WITH RETURN FOR
	                SELECT f.ProgramSourceID AS ProgramID, f.ProgramTargetID AS CalledOrCallingProgramID, p.ProgramName AS CalledOrCallingProgramName
		                   /*,f.Calling_Concat ,f.Lvl*/
				    FROM   (
				            SELECT FromProgramID AS ProgramSourceID ,ToProgramID AS ProgramTargetID /*,Calling_Concat ,Lvl*/
						    FROM SESSION.fin	
							WHERE v_ForwardOrBackward = 1
		
							UNION
		
		                    SELECT ToProgramID AS ProgramSourceID ,FromProgramID AS ProgramTargetID /*,Calling_Concat ,Lvl*/
						    FROM SESSION.fin	
							WHERE v_ForwardOrBackward = -1
				           ) f
					             INNER JOIN (
												SELECT pgm.ProgramID ,COALESCE(pa.AliasName, pgm.ProgramName) AS ProgramName
												FROM Programs pgm
													LEFT OUTER JOIN ProgramAliases pa  ON pgm.ProgramID = pa.ProgramId AND pa.AliasType = 0
											) p ON f.ProgramTargetID = p.ProgramID
					ORDER BY f.ProgramTargetID ;
	
	
                   OPEN crs;

            END;
			
		END;	

END	ss
