Pour les besoins d’une étude d’impact avant une migration, j’ai besoin de récupérer la liste des rapports et la base dans laquelle ils vont piocher leurs données.
Evidemment, quand on a plusieurs centaines de rapports et des dizaines de DataSources accumulés depuis des années, on oublie vite l’idée de faire le référencement à la main.
Surtout quand on sait qu’on a tout dans la base de données de Reporting Services (ReportServer).
J’ai donc écrit une requête qui pioche les informations dans la table dbo.Catalog.
Attention, il y a:
- du type XML à la toque pour creuser dans la définition RDL
- des CTE pour simplifier (ou presque)
Je ne vais pas m’étendre sur une explication de texte. Sachez juste que la table stocke le RDL (format XML de définition du rapport) dans le champ Content (de type binaire).
Avec quelques requêtes XQuery, on récupère le nom de la source de données partagées ou de la chaîne de connexion (pour de l’embedded).
Evidemment, j’exclue les rapports liés.
WITH datasources AS ( SELECT [Path], [Name], ItemId, CAST(CAST(content as varbinary(max)) as xml).value('/*:DataSourceDefinition[1]/*:Extension[1]', 'varchar(100)') as Provider, CAST(CAST(content as varbinary(max)) as xml).value('/*:DataSourceDefinition[1]/*:ConnectString[1]', 'varchar(100)') as ConnectionString FROM dbo.Catalog WHERE [Type] = 5 ) ,reports AS ( SELECT ItemID, Path, Name ,CAST(CAST(content as varbinary(max)) as xml) as XmlDefinition FROM dbo.Catalog WHERE [Type] = 2 ) SELECT reports.ItemId, reports.[Path], reports.Name, T2.ds.value('(.//*:DataSourceReference)[1]', 'varchar(200)') as DataSourceReference, COALESCE(T2.ds.value('(.//*:ConnectString)[1]', 'varchar(200)'),datasources.ConnectionString) as ConnectionString, COALESCE(T2.ds.value('(.//*:DataProvider)[1]', 'varchar(200)'),datasources.Provider) as DataProvider FROM reports CROSS APPLY XmlDefinition.nodes('/*:Report/*:DataSources/*:DataSource') as T2(ds) LEFT JOIN datasources ON datasources.Name = T2.ds.value('(.//*:DataSourceReference)[1]', 'varchar(200)')
PS : après avoir galéré avec les namespaces qui changent entre les version de Reporting Services et de Report Builder, j’ai opté pour la syntaxe wildcard (ex : .//*:DataSourceReference)