Cognos Analytics

 View Only
  • 1.  How to get the report paths from all report objects of cognos analytics catalog

    Posted Thu January 23, 2025 09:14 AM

    I would like to get the report paths from the report objects of the cognos catalog, I'm trying to use the CMOBJECTS, CMOBJNAMES, CMCLASSES and CMOBJPROPS tables to get this information but I'm still confused on how exactly to do this. The only approach that I have tried was using the xml column found in CMOBJNAMES7 table to extract the stored paths, but I'm in doubt because when I join it with the audit table COGIPF_RUNREPORT it seems that there is not much matches.

    Does anyone knows an alternative approach to do this?



    ------------------------------
    Paulo Paulo Mcmiller Crisostomo De Olivei
    ------------------------------


  • 2.  RE: How to get the report paths from all report objects of cognos analytics catalog

    Posted Thu January 23, 2025 05:14 PM

    If you open Cognos in your browser and then use the browser console to run some javascript you can get a list of all reports, and report paths in a csv with the snippet below. Paul Mendelson has written about using the expressbus api in the forum before. It does a pretty thorough search of all the objects in a folder and works pretty quickly.

    let objectId = 'xxxxxxxxxxxxxxxxxxxxxx'; // ID of content folder you want to search
    __glassAppController.glassContext.services.ajax.ajax({
      type: 'GET',
      url: __glassAppController.glassContext.gateway + 
           `/v1/expressbus/content-manager?searchPath=storeID('${objectId}')//report|storeID('${objectId}')//interactiveReport&properties=id,defaultName,searchPath`
    })
    .then(function(response) {
      
      let csvContent = "ReportName,ObjectId,Search Path,Path URL\n";
    
      response.forEach(item => {
        let reportName  = item.defaultName        || "";
        let objectId    = item.id                || "";
        let searchPath  = item.searchPath        || "";
        let pathUrl     = item?._meta?.links?.path?.url || "";
        
        function csvSafe(str) {
          return `"${String(str).replace(/"/g, '""')}"`;
        }
    
        csvContent += [
          csvSafe(reportName),
          csvSafe(objectId),
          csvSafe(searchPath),
          csvSafe(pathUrl)
        ].join(",") + "\n";
      });
    
      let blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    
      let link = document.createElement("a");
      if (link.download !== undefined) {
        let url = URL.createObjectURL(blob);
        link.setAttribute("href", url);
        link.setAttribute("download", "report_export.csv"); // Change the filename if desired
        link.style.visibility = 'hidden';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      }
    })
    .catch(function(error) {
      console.error('Error fetching data:', error);
    });
    
    
     
     


    ------------------------------
    Michael Webb
    ------------------------------



  • 3.  RE: How to get the report paths from all report objects of cognos analytics catalog

    Posted Fri January 24, 2025 03:57 AM

    Thanks for the shoutout Michael!

    It's also worth mentioning that the searchpath parameter is xpath formatted. So you could get all reports (that your user has access to) in Cognos with searchPath=//report. searchPath=//account/folder[@name="My Folders"]//report would get all reports inside user My Folders. 

    I use this solution to populate my Object Search tool. 

    The expressbus api supports paginating outputs, which lets me pull it in batches to prevent timeouts.

    https://server/ibmcognos/bi/v1/expressbus/content-manager?searchPath=//report|//interactiveReport&properties=defaultName,parent,ancestors,id,defaultDescription,searchPath,metadataModelPackage,paths,module,owner,parameters,creationTime,modificationTime,defaultPortalAction,executionFormat,retentions,routingServerGroup,type&options={refProps:[{refPropName:%22ancestors%22,properties:[%22defaultName%22,%22id%22,%22name%22,%22searchPath%22,%22type%22]},{refPropName:%22owner%22,properties:[%22defaultName%22,%22id%22,%22name%22,%22searchPath%22,%22type%22]},{refPropName:%22paths%22,properties:[%22defaultName%22,%22type%22]},{refPropName:%22parent%22,properties:[%22defaultName%22,%22id%22,%22name%22,%22searchPath%22,%22type%22]},{refPropName:%22metadataModelPackage%22,properties:[%22defaultName%22,%22id%22,%22searchPath%22,%22type%22]},{refPropName:%22module%22,properties:[%22defaultName%22,%22id%22,%22searchPath%22,%22type%22]}],maxObjects:500,skipObjects:1000}

    (yeah, this is sorta an add, but a man's gotta eat)

    There are a few other parameter options in the expressbus API, but they're not fully documented so a lot of customers are hesitant to use it. Hey Tim! This is why I keep pushing for this API to be included in the published API stack. It's one of the most useful undocumented APIs Cognos has!



    ------------------------------
    Paul Mendelson Product Manager
    Product Manager
    PMsquare
    ------------------------------



  • 4.  RE: How to get the report paths from all report objects of cognos analytics catalog

    Posted Fri January 24, 2025 12:17 PM

    Hi Paul! 
    Great clarification about the xpath and pagination. I will say this api can be a little dangerous without pagination. If you don't paginate and run it on the Team Content folder and you have a large org with thousands of reports and add "specification" on the list of properties and run it for all reports I have basically grinded down our cognos instance to a halt for all our users. I think the recursive lookup is does is meant for pinpoint searches for the UI to display stuff however it isn't throttled at all. I was surprised that it even let me make a request that large without an automatic timeout or maximum request size. 

    I actually used this expressbus api to parse all specifications xmls for all reports in a folder to gather metadata, relationships, data item definitions, chart types, queries, security groups/roles, and more in csv outputs to try to standardize metadata collection for our financial reporting. Since I don't have access to the  SDK or framework manager this has been a pretty fun learning experience and I am making my own admin tools to run as services in Cognos. All thanks to you Paul! I owe all my growth to your early encouragement and direction as I started reverse engineering it all haha. 



    ------------------------------
    Michael Webb
    ------------------------------



  • 5.  RE: How to get the report paths from all report objects of cognos analytics catalog

    Posted Fri February 07, 2025 12:18 PM
    Edited by Paulo McMiller Mon February 10, 2025 08:58 AM

    Thank you so much, Michael and Paul. I really appreciate your help; the JavaScript code worked fine.

    However, if I may, I would like to get back to discussing the approach of obtaining the report paths by querying the CMOBJ[..] tables. I would like to track those reports and merge them with their activity found in the COGIPF tables. Since these tables are constantly updated, it would be more helpful to have that information by querying them. The only problem I'm struggling with is that I am unable to get a reliable match for the report paths from those tables. Do you know of any other table besides CMOBJNAMES7 (which seems to be missing some paths) that has all the report paths? Or do you have any strategy to construct them from there?



    ------------------------------
    Paulo McMiller
    ------------------------------



  • 6.  RE: How to get the report paths from all report objects of cognos analytics catalog

    Posted 30 days ago

    @Michael Webb - how do you get to the browser console?



    ------------------------------
    brenda grossnickle
    BI Programmer Analyst
    FIS
    ------------------------------



  • 7.  RE: How to get the report paths from all report objects of cognos analytics catalog
    Best Answer

    Posted 30 days ago

    I wrote a MS SQL stored procedure. Below is the tsql code to (1) create a database called temp1 (2) create a stored procedure in temp1 to read the cognos content store looking for reports and queries and writing them to a table (3) call the stored procedure passing in the name of the cognos database - exec cm_ListAllReportsAndQueries 'Store32cm_Cognos11' (4) display the temp1 table CM_ReportList. 

    I wrote the stored procedure so that it could be created and run from a database other than the cognos content store. 

    --drop database temp1
    
    create database temp1
    
    go
    
    use  temp1
    
    go
    
    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[cm_ListAllReportsAndQueries]') AND type in (N'P', N'PC'))
    DROP PROCEDURE [dbo].[cm_ListAllReportsAndQueries]
    GO
    
    CREATE PROCEDURE [dbo].[cm_ListAllReportsAndQueries]
    
    /***************************************************************
    
    cm_ListAllReportsAndQueries creates table cm_reportlist which lists all the
    reports and queries. 
    
    Example
    =======
    
    -- pass in the Cognos CM Store
    exec cm_ListAllReportsAndQueries 'Store32CM_Cognos11' 
    
    QUERIES
    ========
    
    -- select rows from the output table cm_reportList
    select [Directory Path],[Report Name],[Package Name],[Owner Name],[Type],[Modified],[Created],[CMID],[PCMID],[mapdlocaleid], ReportList_Create from cm_reportlist
    
    
    Changes1
    ========
    2/11/2025 - bxg - created sproc               
    
    ****************************************************************/
    
    @pCognosCMDataBase varchar(28)	 
    
    AS  
    
    BEGIN  
    
          SET NOCOUNT ON
    
    	  declare @note varchar(500) = ''
    	  declare @rowcount int = 0
    	  declare @DBName nvarchar(128) = db_name()
    	  declare @SQL nvarchar(max) = ''
    	  declare @SQL2 nvarchar(max) = ''
    
         /* IF @pReportSpecification IS NULL or @pReportSpecification <> 0
             Set @pReportSpecification = 1    */
          IF @pCognosCMDataBase IS NULL or @pCognosCMDataBase = '' or not exists (select top 1 1 from sysdatabases)
             begin
    			Print 'Invalid Cognos CM Database Name: ' + isnull(@pCognosCMDataBase, 'NULL')
    		 end
         
    		IF OBJECT_ID('[dbo].[CM_ReportList]') IS NOT NULL 
    			DROP TABLE [dbo].[CM_ReportList] 
    
    		CREATE TABLE [dbo].[CM_ReportList] ( 
    			[Directory Path]	VARCHAR(512)      NULL,
    			[Report Name]		NVARCHAR(256)     NULL,
    			[Package Name]		NVARCHAR(256)     NULL,
    			[Owner Name]		NVARCHAR(256)	  NULL,
    			[Type]				VARCHAR(128)	  NULL,
    			[Modified]			DATETIME          NULL,
    			[Created]			DATETIME          NULL,
    			[CMID]				INT               NULL,
    			[PCMID]				INT               NULL,
    			[mapdlocaleid]		SMALLINT          NULL,
    			[ReportList_Create]	DATETIME		  NULL) 
    
    	 set @SQL = N'
    	  use  ' + @pCognosCMDataBase + N'
    
    	 /** query on the Cognos Content Store to find reports and queries (10 and 37) **/
          ; with base_query as
          (
    		  select classid, cmobjects.cmid, cmobjects.pcmid, cmobjnames.name as reportname, cmobjects.disabled, cmobjnames.mapdlocaleid,
    			 cmobjects.CREATED, cmobjects.modified
    			  from cmobjects , cmobjnames
    			  where cmobjects.cmid = cmobjnames.cmid and (cmobjects.disabled is null or cmobjects.disabled <> 1)
    			  and classid in (10, 37) 
    			  and cmobjnames.mapdlocaleid in  (24,96, 92)
    		  union
    		  select classid, cmobjects.cmid as cmid, cmobjects.pcmid, cmobjnames.name as reportname, cmobjects.disabled, cmobjnames.mapdlocaleid,
    			 cmobjects.CREATED, cmobjects.modified
    			  from cmobjects , cmobjnames
    			  where cmobjects.cmid = cmobjnames.cmid and (cmobjects.disabled is null or cmobjects.disabled <> 1)
    			  and  cmobjects.cmid in (select distinct cmobjects.pcmid
    			  from cmobjects)
    			   and cmobjnames.mapdlocaleid in (24,96,92)      
          ),
          
         /** recursive query through the folders to build the report and query path **/
          ctebuildpath as
          (
    		  select base_query.cmid,
    			  base_query.pcmid,
    			  base_query.reportname,
    			  base_query.created,     
    			  base_query.modified,    
    			  base_query.[disabled],
    			  base_query.mapdlocaleid,
    			  1 as Hlevel,classid,
    			  cast(base_query.reportname as varchar(500))as directory_path
    			  from base_query where reportname = ''Team Content'' or reportname = ''My Folders'' 
    		  union all
    		  select recur.cmid,
    			  recur.pcmid,
    			  recur.reportname,
    			  recur.created,    
    			  recur.modified,         
    			  recur.[disabled],
    			  recur.mapdlocaleid,
    			  cte.Hlevel+1 as Hlevel,recur.classid,
    			  cast(cte.directory_path + ''>'' +  recur.reportname as varchar(500))as directory_path
    			  from base_query as recur,
    			  ctebuildpath as cte
    			  where cte.cmid = recur.pcmid
          ),    
    
    	  /** charindex('']/package[@name='', cast(spec as  varchar(max)))+17 as startposition,
    		  charindex('']/model[@name='', cast(spec as  varchar(max)))-18-charindex('']/package[@name='', cast(spec as  varchar(max))) as endposition
    	  **/
          report_spec as 
          (
    		  select cast(spec as  varchar(max)) as spec, c.cmid		  
    		  from cmobjprops7 c inner join ctebuildpath b
    				on c.cmid = b.cmid
    		  where spec is not null 
          ),
    
    	  /** get the package name **/
    	  package as
    		 (
    		 SELECT cmrefnoord1.cmid AS pid,
    		 cmobjnames.name AS package_name
    		 FROM cmrefnoord1
    		 INNER JOIN cmobjects
    		 ON cmrefnoord1.refcmid = cmobjects.cmid
    		 INNER JOIN cmobjnames
    		 ON cmobjects.cmid = cmobjnames.cmid
    		 WHERE cmrefnoord1.propid = 31
    		 AND cmobjnames.ISDEFAULT=1
    		 ), 
    
        /** query to find the Owner of the reports and queries **/
        owner_name as 
        (
    		select a.name, b.cmid
    		  from cmobjprops33 a,  cmobjnames b, cmrefnoord2 c, cmobjects d, cmclasses e, ctebuildpath cte
    		  where b.cmid = c.cmid
    		  and a.cmid = c.refcmid
    		  and b.cmid = d.cmid
    		  and d.classid = e.classid
    		  and (e.name = ''report'' or e.NAME = ''query'')
    		  and cte.CMID = b.cmid
          ),
    
    	  /** get rid of duplicates **/
    	  get_distinct as
    	  (
     		SELECT distinct directory_path as [Directory Path], reportname as [Report Name], package.package_name as [Package Name],
    					ISNULL(Owner_name.name, ''Unknown'') as ''Owner Name'', Case classid When 10 Then ''Report'' Else ''Query'' End as Type,  
    					Modified, Created,
    					cte.cmid as CMID,  cte.pcmid as PCMID, mapdlocaleid 
    				FROM ctebuildpath cte inner join report_spec rep
    							on cte.cmid = rep.cmid 
    							full outer join owner_name 
    							on cte.CMID = owner_name.cmid
    							left join package
    							on package.pid = cte.cmid
    				WHERE cte.classid in (10, 37)
    	 ) '
    
    	-- sql literal cannot be more than 4000 characters. so splitting the dynamic sql into two parts
    	Set @SQL2 = '/**  sort My Folders first, then within My Folder sort by Owner Name. WIthin the second group (Public Folders and ??) sort by Directory Path **/
    		Insert into ' + @dbname	 + N'..CM_ReportList ([Directory Path],[Report Name],[Package Name],[Owner Name],[Type],[Modified],[Created],[CMID],[PCMID],[mapdlocaleid], ReportList_Create)
    			Select [Directory Path],[Report Name],[Package Name],[Owner Name],[Type],[Modified],[Created],[CMID],[PCMID],[mapdlocaleid], getdate()
    				from get_distinct
    				ORDER by 
    					CASE WHEN LEFT([directory path], 11)  = ''My Folders>'' THen 0 ELSE 1 END,
    					CASE WHEN LEFT([directory path], 11)  = ''My Folders>'' THen [Owner Name] ELSE [Directory Path] END,
    					[directory path]  '
    					
    					 
    	set @sql = @sql + @sql2
    
    	--exec util_longprint @sql 
    
    	exec sp_executesql @SQL    
    
    	set @rowcount = @@rowcount
    		
    	Print 'CM Create ReportList created with ' + cast(@RowCount as varchar(12)) + ' rows.'
    		           
    END
    
    GO
    
    exec cm_ListAllReportsAndQueries 'Store32cm_Cognos11'
    
    select * from CM_ReportList
    
    
    



    ------------------------------
    brenda grossnickle
    BI Programmer Analyst
    FIS
    ------------------------------