DYNAMIC RESULT SETS 1
LANGUAGE SQL
BEGIN


    -- clean up temp table if exists 
	BEGIN
		DECLARE CONTINUE HANDLER FOR SQLSTATE '42704'
		BEGIN END;
		
		COMMIT;

		DROP TABLE SESSION.prog_alias_tbl;
		DROP TABLE SESSION.prog_hierarchy1_tbl;
		DROP TABLE SESSION.prog_hierarchy2_tbl;
		DROP INDEX SESSION.prog_alias_tbl_cidx1;
		DROP INDEX SESSION.prog_hierarchy2_tbl_ncidx3;
	END;

    BEGIN
            
             DECLARE v_Level, v_RC INTEGER DEFAULT 1;
            
            
             DECLARE GLOBAL TEMPORARY TABLE SESSION.prog_alias_tbl
			( 
			    ProgramID INTEGER ,
				ProgramName VARCHAR(256) ,
				ProgramNameU VARCHAR(256) ,
				ProgramTypeID INTEGER ,
				OccurID INTEGER ,
				Ancestor VARCHAR(256),
				AncestorU VARCHAR(256)
			)ON COMMIT PRESERVE ROWS
			    NOT LOGGED;

            CREATE INDEX prog_alias_tbl_cidx1 ON SESSION.prog_alias_tbl (ProgramID ASC) CLUSTER;  

            
             DECLARE GLOBAL TEMPORARY TABLE SESSION.prog_hierarchy1_tbl
			( 
			    RootProgramID INTEGER ,
				RootProgramName VARCHAR(256) ,
				RootProgramTypeID INTEGER ,
				RootProgramOccurID INTEGER ,
				ProgramID INTEGER ,
				ProgramName VARCHAR(256) ,
				ProgramNameU VARCHAR(256) ,
				ProgramTypeID INTEGER ,
				ProgramOccurID INTEGER ,
				Lvl INTEGER 
			)ON COMMIT PRESERVE ROWS
			    NOT LOGGED;
            
            
            DECLARE GLOBAL TEMPORARY TABLE SESSION.prog_hierarchy2_tbl
			( 
			    RootProgramID INTEGER ,
				RootProgramName VARCHAR(256) ,
				RootProgramTypeID INTEGER ,
				RootProgramOccurID INTEGER ,
				ProgramID INTEGER ,
				ProgramName VARCHAR(256) ,
				ProgramTypeID INTEGER ,
				ProgramOccurID INTEGER ,
				Lvl INTEGER ,
				RN BIGINT 
			)ON COMMIT PRESERVE ROWS
			    NOT LOGGED;

           CREATE INDEX prog_hierarchy2_tbl_ncidx3 ON SESSION.prog_hierarchy2_tbl (ProgramID, RN, RootProgramID, RootProgramName, RootProgramOccurID) ;
           
           
           

             INSERT INTO SESSION.prog_alias_tbl (ProgramID, ProgramName, ProgramNameU, ProgramTypeID, OccurID, Ancestor, AncestorU)
             SELECT t.ProgramID, t.ProgramName, UPPER(t.ProgramName), t.ProgramTypeID, t.OccurID,  t.AncestorName AS Ancestor, UPPER(t.AncestorName) AS AncestorU
	         FROM TABLE( 
			            fGetProgram_Ancestor_Aliases( CAST(NULL AS INTEGER) ) 
			            )t ;
            COMMIT; 


            INSERT INTO SESSION.prog_hierarchy1_tbl (RootProgramID, RootProgramName, RootProgramTypeID, RootProgramOccurID, ProgramID, ProgramName, ProgramNameU, ProgramTypeID, ProgramOccurID, Lvl)
		    SELECT p.ProgramID AS RootProgramID,
		            p.ProgramName AS RootProgramName,
		            p.ProgramTypeID AS RootProgramTypeID,
		            p.OccurID AS RootProgramOccurID,
		            p.ProgramID,
		            p.ProgramName,
		            p.ProgramNameU,
		            p.ProgramTypeID,
		            p.OccurID AS ProgramOccurID,
		            0 AS Lvl
		     FROM SESSION.prog_alias_tbl p
		     WHERE p.ProgramTypeID IN (8);
             COMMIT;
             


              -- get an hierarchy
			  WHILE  (v_RC > 0 AND v_Level < 1000) -- no more than 1000 cycles
			         DO
						 
						 COMMIT; 
						 INSERT INTO SESSION.prog_hierarchy1_tbl (RootProgramID, RootProgramName, RootProgramTypeID, RootProgramOccurID, ProgramID, ProgramName, ProgramNameU, ProgramTypeID, ProgramOccurID, Lvl)
			             SELECT parent.RootProgramID,
					            parent.RootProgramName,
					            parent.RootProgramTypeID,
					            parent.RootProgramOccurID,
					            p.ProgramID,
					            p.ProgramName,
					            p.ProgramNameU,
					            p.ProgramTypeID,
					            p.OccurID,
					            parent.Lvl + 1 AS Lvl
					     FROM SESSION.prog_alias_tbl p
					          INNER JOIN SESSION.prog_hierarchy1_tbl parent ON  parent.ProgramID != p.ProgramID AND parent.ProgramNameU = p.AncestorU
					          LEFT OUTER JOIN SESSION.prog_hierarchy1_tbl i ON  i.ProgramID = p.ProgramID   -- avoid to consider same program multiple times                                         
					     WHERE p.ProgramTypeID IN (15, 16)
					           AND (p.ProgramTypeID IN (15, 16)
					           AND parent.ProgramTypeID IN (8)) 
					           AND i.ProgramID IS NULL
                               AND NULLIF(p.Ancestor, '') IS NOT NULL ;

			              GET DIAGNOSTICS v_RC = ROW_COUNT; 
			
			              SET v_Level = v_Level + 1;
			                   
			                   
			   END WHILE;
			   

             -- calculate RN
             INSERT INTO SESSION.prog_hierarchy2_tbl (RootProgramID, RootProgramName, RootProgramTypeID, RootProgramOccurID, ProgramID, ProgramName, ProgramTypeID, ProgramOccurID, Lvl, RN)
		     SELECT prog_hierarchy.RootProgramID,
		            prog_hierarchy.RootProgramName,
		            prog_hierarchy.RootProgramTypeID,
		            prog_hierarchy.RootProgramOccurID,
		            prog_hierarchy.ProgramID,
		            prog_hierarchy.ProgramName,
		            prog_hierarchy.ProgramTypeID,
		            prog_hierarchy.ProgramOccurID,
		            prog_hierarchy.Lvl,
		            ROW_NUMBER() OVER(PARTITION BY prog_hierarchy.ProgramID ORDER BY prog_hierarchy.Lvl DESC) AS RN
		     FROM SESSION.prog_hierarchy1_tbl AS prog_hierarchy;
             COMMIT;

       
	 
           


         
           
           BEGIN
	            
	             DECLARE crs CURSOR WITH RETURN FOR
	             SELECT prg.ProgramID,
				   prg.ProgramName,
				   prg.ProgramTypeID,
				   COALESCE(pth.PathStr, '') AS ProgramPathStr,
				   prg.Halstead_dn1,
				   prg.Halstead_tN1,
				   prg.Halstead_dn2,
				   prg.Halstead_tN2,
				   prg.CyclomaticScore,
				   prg.TotalStmts,
				   prg.DeadStmts,
				   prg.Sloc,
				   VARCHAR_FORMAT(pf.LastUpdated, 'YYYY-MM-DD HH24:MI:SS') AS LastUpdated
				   --CONVERT(VARCHAR(19), pf.LastUpdated, 120) AS LastUpdated
			 FROM
			 (
								SELECT m.ProgramID,
									   m.ProgramName,
									   m.ProgramTypeID,
									   m.ProgramOccurID,
									  COALESCE(SUM(m.Halstead_Var_D_CNT), 0) AS Halstead_dn1,
									  COALESCE(SUM(m.Halstead_Var_CNT), 0) AS Halstead_tN1,
									  COALESCE(SUM(m.Halstead_StatementType_D_CNT), 0) AS Halstead_dn2,
									  COALESCE(SUM(m.Halstead_StatementType_CNT), 0) AS Halstead_tN2,
									  COALESCE(SUM(m.CyclomaticScore), 0) AS CyclomaticScore,
									  COALESCE(SUM(m.OccurID_CNT), 0) AS TotalStmts,
									  COALESCE(SUM(m.DeadStmts_NumOfStatements), 0) AS DeadStmts,
									  COALESCE(SUM(m.SLOC), 0) AS Sloc
								FROM
								    (
									   SELECT CASE
											    WHEN h.RootProgramID IS NOT NULL
											    THEN h.RootProgramID
											    ELSE p.ProgramId
											END AS ProgramID,
											CASE
											    WHEN h.RootProgramID IS NOT NULL
											    THEN h.RootProgramName
											    ELSE p.ProgramName
											END AS ProgramName,
											CASE
											    WHEN h.RootProgramID IS NOT NULL
											    THEN h.RootProgramTypeID
											    ELSE p.ProgramTypeID
											END AS ProgramTypeID,
											CASE
											    WHEN h.RootProgramID IS NOT NULL
											    THEN h.RootProgramOccurID
											    ELSE p.OccurID
											END AS ProgramOccurID,
											hld1.Halstead_Var_D_CNT,
											hld1.Halstead_Var_CNT,
											hld2.Halstead_StatementType_D_CNT,
											hld2.Halstead_StatementType_CNT,
											cycl.CyclomaticScore,
											totalStmts.OccurID_CNT,
											CASE
											    WHEN p.ProgramTypeID = 1
											    THEN deadStmts.NumOfStatements_COBOL
											    ELSE deadStmts.NumOfStatements_OTHERS
											END AS DeadStmts_NumOfStatements,
											statsLines.SLOC
									   FROM SESSION.prog_alias_tbl p
											--Halstead operators-Variables
										   LEFT OUTER JOIN
													   (
													      SELECT os.ProgID AS ProgramID,
															    COUNT(v.VarName) AS Halstead_Var_CNT,
															    COUNT(DISTINCT v.VarName) AS Halstead_Var_D_CNT
														  FROM StatementReference sr
															  INNER JOIN OccurrencesStmt os ON os.OccurID = sr.OccurID
															  INNER JOIN Variables v ON v.VarID = sr.ResourceID
														  WHERE   sr.ResourceType = 4
														  GROUP BY os.ProgID 
													   ) hld1 ON p.ProgramID = hld1.ProgramID
											--Halstead operands-StatementType
										   LEFT OUTER JOIN
													   (
														  SELECT os.ProgID AS ProgramID,
															    COUNT(os.StatementType) AS Halstead_StatementType_CNT,
															    COUNT(DISTINCT os.StatementType) AS Halstead_StatementType_D_CNT
														  FROM OccurrencesStmt os
														  GROUP BY os.ProgID
													   ) hld2 ON p.ProgramID = hld2.ProgramID
										   LEFT OUTER JOIN
													   (
														  SELECT ProgramID,
															    CyclomaticScore
														  FROM ProgramCyclomaticScores
													   ) cycl ON p.ProgramID = cycl.ProgramID
										   LEFT OUTER JOIN
													   (
														  SELECT os.ProgID AS ProgramID,
															    COUNT(os.OccurID) AS OccurID_CNT
														  FROM OccurrencesStmt os
														  GROUP BY os.ProgID
													   ) totalStmts ON p.ProgramID = totalStmts.ProgramID
											--deadStmtsOTHERS + deadStmtsCOBOL
										   LEFT OUTER JOIN
													   (
														  SELECT ProgramID,
																	-- COBOL
															    SUM(CASE
																	  WHEN par.UnreachablePara = -1
																	  THEN par.NumOfStatements
																	  ELSE 0
																   END) AS NumOfStatements_COBOL,
																	-- OTHERS
															    SUM(CASE
																	  WHEN par.OrdinalNum != 1
																		  AND par.IsExitPara = 0
																		  AND sr.ResourceID IS NULL
																	  THEN par.NumOfStatements
																	  ELSE 0
																   END) AS NumOfStatements_OTHERS
														  FROM Paragraphs par
															  LEFT OUTER JOIN
																		  (
																			 SELECT sr.ResourceID
																			 FROM StatementReference sr
																			 WHERE sr.ResourceType = 2
																			 GROUP BY sr.ResourceID
																		  ) sr ON par.ParaID = sr.ResourceID
														  GROUP BY par.ProgramID
													   ) deadStmts ON p.ProgramId = deadStmts.ProgramID
											-- sloc from statistics
										   LEFT OUTER JOIN
													   (
														  SELECT p.ProgramID,
															    sts.SLOC
														  FROM Occurrences o
															  INNER JOIN Programs p ON p.OccurID = o.OccurID
																					 AND p.ProgramTypeID IN (1, 8)	 
															  INNER JOIN
																	   (
																		  SELECT s.PathID,
																			    s.Code AS SLOC
																		  FROM StatisticsLines s
																		  WHERE s.ScopeId IN (13, 15)
																	   ) sts ON sts.PathID = o.PathID
													   ) statsLines ON p.ProgramID = statsLines.ProgramID
										   LEFT OUTER JOIN SESSION.prog_hierarchy2_tbl h ON p.ProgramID = h.ProgramID
																		                    AND h.RN = 1
								    ) m
								    GROUP BY m.ProgramID,
										   m.ProgramName,
										   m.ProgramTypeID,
										   m.ProgramOccurID
				) prg
			 LEFT OUTER JOIN Occurrences occ ON occ.OccurID = prg.ProgramOccurID
			 LEFT OUTER JOIN Paths pth ON pth.PathID = occ.PathID
			 LEFT OUTER JOIN
						  (
							 SELECT pth.PathID,
								   COALESCE(mm.LastUpdateDate, mnm.UpdateDate, mlm.UpdateDate, zcc.dateTimeLastModified, zcb.dateTimeLastModified) AS LastUpdated
							 FROM Pj_File pf
								 INNER JOIN Pj_File_VS_MainframeMembers pfmm ON pf.ID_File = pfmm.Pj_FileID
								 INNER JOIN Paths pth ON UPPER(pth.PathStr) = UPPER(pf.FilePath)
								 LEFT OUTER JOIN MFMembers mm ON pfmm.MemberType IN (0, 1, 2)
															   AND mm.MemberID = pfmm.MemberID
								 LEFT OUTER JOIN MFNaturalMembers mnm ON pfmm.MemberType IN (3, 6)
																	AND mnm.NatMemberID = pfmm.MemberID
								 LEFT OUTER JOIN MFLibrarianMembers mlm ON pfmm.MemberType = 4
																	  AND mlm.LibrarianMemberID = pfmm.MemberID
								 LEFT OUTER JOIN ZMF_CM_Components zcc ON pfmm.MemberType = 5
																	 AND zcc.ID = pfmm.MemberID
								 LEFT OUTER JOIN ZMF_CM_Components_Baseline zcb ON pfmm.MemberType = 7
																			AND zcb.ID = pfmm.MemberID
						  ) pf ON pf.PathID = occ.PathID
	           ORDER BY 1, 2;  
	             

                 OPEN crs;

            END;
                    
			
	END;	
	
END