├── CognosScripts ├── HolidayCalendar.js ├── HolidayCalendarControl.js ├── ObjectMethods.js ├── OrderOfMethodsCustomControl.js ├── OrderOfMethodsPageModule.js ├── ParamDisplay.js ├── ParameterCapture.js ├── ParameterDisplay.js ├── ParameterToText.js ├── PromptAutoFinish.js ├── PromptButton.js ├── PromptDateDefault.js ├── PromptFinish.js ├── PromptIncrementAndRun.js ├── PromptLoadValuesFromQuery.js ├── Prompts.js ├── README.md ├── cleanParams.js ├── json.js ├── json2xml.js ├── mapOpenLayers.js └── xml2json.js ├── ContentStore ├── ADSI.sql ├── BrokenShortcuts.sql ├── Capabilities.ps1 ├── CognosScheduleEmailRecients.sql ├── ContentStoreCMIDSearch.sql ├── ContentStoreDoc.txt ├── LocateSchedules.sql ├── ModuleAndModelSpecs.sql ├── ModulesAndPackages.ps1 ├── ObjectCapabilities.ps1 ├── ObjectPermissions.ps1 ├── OutputSpecs.sql ├── OwnedObjects.sql ├── PackageReference.sql ├── PermissionsPerUser.sql ├── README.md ├── RoleGroupMembership.ps1 ├── SpecBackup │ ├── README.md │ ├── ReportBackup.ps1 │ ├── export.ps1 │ └── push.ps1 ├── capabilities.sql ├── udf_CognosPermissions.sql └── udf_ConvertFromBase10.sql ├── LICENSE ├── Maintenance ├── MaintenanceWindow │ ├── CognosMaintenance.ps1 │ ├── CognosStart.ps1 │ ├── CognosStop.ps1 │ └── README.md └── SSL │ ├── README.md │ ├── RequestCognosServerCert.ps1 │ ├── SSLCertExpiration.csv │ └── SSLExpiration.ps1 ├── README.md ├── RESTAPI ├── ModuleBusinessNames.ps1 ├── README.md ├── REST API Example.ps1 ├── fn.ps1 └── getCSV.ps1 ├── ReportSpecifications ├── Bursting.txt ├── CommaDelimitedList.txt ├── ComplexLineChart.txt ├── CrosstabWithRowLabelHeaders.txt ├── Date Calculations.txt ├── Parameter Reporter.txt ├── Parameter Value Automation.txt ├── Prompt Scripts.txt ├── README.md ├── Scriptable Reports - Order of Methods.txt ├── ToolTips.txt └── VariableOperator.txt └── SDK └── README.md /CognosScripts/HolidayCalendar.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | // HoldayCalendar.js 3 | // Holiday Calendar 4 | // contains dates that are holidays 5 | // provides a function to determin if 6 | 7 | function HolidayCalendar() { 8 | }; 9 | 10 | HolidayCalendar.Holidays = []; 11 | HolidayCalendar.Holidays.push(new Date(2016,0,1)); 12 | HolidayCalendar.Holidays.push(new Date(2016,0,18)); 13 | HolidayCalendar.Holidays.push(new Date(2016,1,15)); 14 | HolidayCalendar.Holidays.push(new Date(2016,4,30)); 15 | HolidayCalendar.Holidays.push(new Date(2016,6,4)); 16 | HolidayCalendar.Holidays.push(new Date(2016,8,5)); 17 | HolidayCalendar.Holidays.push(new Date(2016,10,11)); 18 | HolidayCalendar.Holidays.push(new Date(2016,10,24)); 19 | HolidayCalendar.Holidays.push(new Date(2016,10,25)); 20 | HolidayCalendar.Holidays.push(new Date(2016,11,26)); 21 | HolidayCalendar.Holidays.push(new Date(2017,0,2)); 22 | HolidayCalendar.Holidays.push(new Date(2017,0,16)); 23 | HolidayCalendar.Holidays.push(new Date(2017,1,20)); 24 | HolidayCalendar.Holidays.push(new Date(2017,4,29)); 25 | HolidayCalendar.Holidays.push(new Date(2017,6,4)); 26 | HolidayCalendar.Holidays.push(new Date(2017,8,4)); 27 | HolidayCalendar.Holidays.push(new Date(2017,10,10)); 28 | HolidayCalendar.Holidays.push(new Date(2017,10,23)); 29 | HolidayCalendar.Holidays.push(new Date(2017,10,24)); 30 | HolidayCalendar.Holidays.push(new Date(2017,11,25)); 31 | HolidayCalendar.Holidays.push(new Date(2018,0,1)); 32 | HolidayCalendar.Holidays.push(new Date(2018,0,15)); 33 | HolidayCalendar.Holidays.push(new Date(2018,1,19)); 34 | HolidayCalendar.Holidays.push(new Date(2018,4,28)); 35 | HolidayCalendar.Holidays.push(new Date(2018,6,4)); 36 | HolidayCalendar.Holidays.push(new Date(2018,8,3)); 37 | HolidayCalendar.Holidays.push(new Date(2018,10,12)); 38 | HolidayCalendar.Holidays.push(new Date(2018,10,22)); 39 | HolidayCalendar.Holidays.push(new Date(2018,10,23)); 40 | HolidayCalendar.Holidays.push(new Date(2018,11,25)); 41 | HolidayCalendar.Holidays.push(new Date(2019,0,1)); 42 | HolidayCalendar.Holidays.push(new Date(2019,0,21)); 43 | HolidayCalendar.Holidays.push(new Date(2019,1,18)); 44 | HolidayCalendar.Holidays.push(new Date(2019,4,27)); 45 | HolidayCalendar.Holidays.push(new Date(2019,6,4)); 46 | HolidayCalendar.Holidays.push(new Date(2019,8,2)); 47 | HolidayCalendar.Holidays.push(new Date(2019,10,11)); 48 | HolidayCalendar.Holidays.push(new Date(2019,10,28)); 49 | HolidayCalendar.Holidays.push(new Date(2019,10,29)); 50 | HolidayCalendar.Holidays.push(new Date(2019,11,25)); 51 | HolidayCalendar.Holidays.push(new Date(2020,0,1)); 52 | HolidayCalendar.Holidays.push(new Date(2020,0,20)); 53 | HolidayCalendar.Holidays.push(new Date(2020,1,17)); 54 | HolidayCalendar.Holidays.push(new Date(2020,4,25)); 55 | HolidayCalendar.Holidays.push(new Date(2020,6,3)); 56 | HolidayCalendar.Holidays.push(new Date(2020,8,7)); 57 | HolidayCalendar.Holidays.push(new Date(2020,10,11)); 58 | HolidayCalendar.Holidays.push(new Date(2020,10,26)); 59 | HolidayCalendar.Holidays.push(new Date(2020,10,27)); 60 | HolidayCalendar.Holidays.push(new Date(2020,11,25)); 61 | HolidayCalendar.Holidays.push(new Date(2021,0,1)); 62 | HolidayCalendar.Holidays.push(new Date(2021,0,18)); 63 | HolidayCalendar.Holidays.push(new Date(2021,1,15)); 64 | HolidayCalendar.Holidays.push(new Date(2021,4,31)); 65 | HolidayCalendar.Holidays.push(new Date(2021,6,5)); 66 | HolidayCalendar.Holidays.push(new Date(2021,8,6)); 67 | HolidayCalendar.Holidays.push(new Date(2021,10,11)); 68 | HolidayCalendar.Holidays.push(new Date(2021,10,25)); 69 | HolidayCalendar.Holidays.push(new Date(2021,10,26)); 70 | HolidayCalendar.Holidays.push(new Date(2021,11,24)); 71 | HolidayCalendar.Holidays.push(new Date(2021,11,31)); 72 | HolidayCalendar.Holidays.push(new Date(2022,0,17)); 73 | HolidayCalendar.Holidays.push(new Date(2022,1,21)); 74 | HolidayCalendar.Holidays.push(new Date(2022,4,30)); 75 | HolidayCalendar.Holidays.push(new Date(2022,5,19)); 76 | HolidayCalendar.Holidays.push(new Date(2022,6,4)); 77 | HolidayCalendar.Holidays.push(new Date(2022,8,5)); 78 | HolidayCalendar.Holidays.push(new Date(2022,10,11)); 79 | HolidayCalendar.Holidays.push(new Date(2022,10,24)); 80 | HolidayCalendar.Holidays.push(new Date(2022,10,25)); 81 | HolidayCalendar.Holidays.push(new Date(2022,11,26)); 82 | HolidayCalendar.Holidays.push(new Date(2023,0,2)); 83 | HolidayCalendar.Holidays.push(new Date(2023,0,16)); 84 | HolidayCalendar.Holidays.push(new Date(2023,1,20)); 85 | HolidayCalendar.Holidays.push(new Date(2023,4,29)); 86 | HolidayCalendar.Holidays.push(new Date(2023,5,19)); 87 | HolidayCalendar.Holidays.push(new Date(2023,6,4)); 88 | HolidayCalendar.Holidays.push(new Date(2023,8,4)); 89 | HolidayCalendar.Holidays.push(new Date(2023,10,10)); 90 | HolidayCalendar.Holidays.push(new Date(2023,10,23)); 91 | HolidayCalendar.Holidays.push(new Date(2023,10,24)); 92 | HolidayCalendar.Holidays.push(new Date(2023,11,25)); 93 | HolidayCalendar.Holidays.push(new Date(2024,0,1)); 94 | HolidayCalendar.Holidays.push(new Date(2024,0,15)); 95 | HolidayCalendar.Holidays.push(new Date(2024,1,19)); 96 | HolidayCalendar.Holidays.push(new Date(2024,4,27)); 97 | HolidayCalendar.Holidays.push(new Date(2024,5,19)); 98 | HolidayCalendar.Holidays.push(new Date(2024,6,4)); 99 | HolidayCalendar.Holidays.push(new Date(2024,8,2)); 100 | HolidayCalendar.Holidays.push(new Date(2024,10,11)); 101 | HolidayCalendar.Holidays.push(new Date(2024,10,28)); 102 | HolidayCalendar.Holidays.push(new Date(2024,10,29)); 103 | HolidayCalendar.Holidays.push(new Date(2024,11,25)); 104 | /* 105 | Use this query against ConformedDimensions: 106 | select 'HolidayCalendar.Holidays.push(new Date(' 107 | + cast(datepart(year, d.FullDate) as varchar(4)) + ',' 108 | + cast(datepart(month, d.FullDate) - 1 as varchar(2)) + ',' 109 | + cast(datepart(day, d.FullDate) as varchar(2)) + '));' 110 | from [Date] d 111 | where d.LegalStateHolidayInd = 'yes' 112 | and year(d.FullDate) >= 2016 113 | order by d.FullDate 114 | */ 115 | 116 | HolidayCalendar.isHoliday = function (d) { 117 | var b = false; 118 | d1 = new Date(d); 119 | d1.setHours(0); 120 | d1.setMinutes(0); 121 | d1.setSeconds(0); 122 | d1.setMilliseconds(0); 123 | //console.log(d); 124 | b = this.Holidays.contains(d1); 125 | //console.log(" " + b.toString()); 126 | return b; 127 | }; 128 | 129 | return HolidayCalendar; 130 | }); -------------------------------------------------------------------------------- /CognosScripts/HolidayCalendarControl.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | // HolidayCalendar.js 3 | // Holiday Calendar 4 | // Exposes one dataset with one category that contains the 5 | // dates of holidays appropriate to the context of the report. 6 | "use strict"; 7 | 8 | var log = function (label, message) { 9 | console.log(" **** " + label + " : " + message); 10 | } 11 | 12 | function HolidayCalendarControl() {}; 13 | 14 | HolidayCalendarControl.prototype.initialize = function ( oControlHost, fnDoneInitializing ) { 15 | log("HolidayCalendar", "initialize" ); 16 | 17 | var bInit = true; 18 | if (bInit) fnDoneInitializing(); 19 | }; 20 | 21 | HolidayCalendarControl.prototype.setData = function( oControlHost, oDataStore ){ 22 | log("HolidayCalendar", "setData" ); 23 | this.m_oDataStore = oDataStore; 24 | }; 25 | 26 | HolidayCalendarControl.prototype.draw = function( oControlHost ){ 27 | log("HolidayCalendar", "draw" ); 28 | }; 29 | 30 | return HolidayCalendarControl; 31 | }); -------------------------------------------------------------------------------- /CognosScripts/OrderOfMethodsCustomControl.js: -------------------------------------------------------------------------------- 1 | define( function() { 2 | "use strict"; 3 | 4 | //var log = function (message) { 5 | // console.log(" Order Of Methods : " + message); 6 | //} 7 | 8 | function AdvancedControl() { 9 | }; 10 | 11 | AdvancedControl.prototype.initialize = function( oControlHost, fnDoneInitializing ) { 12 | this.config = oControlHost.configuration; 13 | this.log = function (message) { 14 | if (!oControlHost.page.ScriptLog) { 15 | var p = document.createElement("pre"); 16 | oControlHost.page.ScriptLog = oControlHost.page.getControlByName("ScriptLog").element.appendChild(p); 17 | } 18 | s = " Order Of Methods : custom control " + this.config.ControlNum + " " + message + "\r\n"; 19 | oControlHost.page.ScriptLog.textContent += s; 20 | //oControlHost.page.getControlByName("ScriptLog").element.childNode.textContent += " Order Of Methods : custom control " + this.config.ControlNum + " " + message + "\r\n"; 21 | console.log(s); 22 | }; 23 | this.log("initialize"); 24 | fnDoneInitializing(); 25 | }; 26 | 27 | AdvancedControl.prototype.destroy = function( oControlHost ) { 28 | this.log("destroy"); 29 | }; 30 | 31 | AdvancedControl.prototype.draw = function( oControlHost ) { 32 | this.log("draw"); 33 | }; 34 | 35 | AdvancedControl.prototype.show = function( oControlHost ) { 36 | this.log("show"); 37 | }; 38 | 39 | AdvancedControl.prototype.hide = function( oControlHost ) { 40 | this.log("hide"); 41 | }; 42 | 43 | AdvancedControl.prototype.isInValidState = function( oControlHost ) { 44 | this.log("isInValidState"); 45 | return true; 46 | }; 47 | 48 | AdvancedControl.prototype.getParameters = function( oControlHost ) { 49 | this.log("getParameters"); 50 | }; 51 | 52 | AdvancedControl.prototype.setData = function( oControlHost, oDataStore ) { 53 | this.log("setData"); 54 | }; 55 | 56 | return AdvancedControl; 57 | }); -------------------------------------------------------------------------------- /CognosScripts/OrderOfMethodsPageModule.js: -------------------------------------------------------------------------------- 1 | define (["/CognosScripts/ObjectMethods.js"], function () { 2 | 3 | 4 | //var log = function (message) { 5 | // console.log(" Order Of Methods : " + message); 6 | //} 7 | 8 | function PageModule() { 9 | }; 10 | 11 | PageModule.prototype.load = function( oPage ) { 12 | if (!oPage.ScriptLog) { 13 | var p = document.createElement("pre"); 14 | oPage.ScriptLog = oPage.getControlByName("ScriptLog").element.appendChild(p); 15 | } 16 | this.log = function (message) { 17 | s = " Order Of Methods : page module " + message + "\r\n"; 18 | oPage.ScriptLog.textContent += s; 19 | //oPage.getControlByName("ScriptLog").element.childNode.textContent += " Order Of Methods : page module " + message + "\r\n"; 20 | console.log(s); 21 | }; 22 | this.log("load"); 23 | }; 24 | 25 | PageModule.prototype.show = function( oPage ) { 26 | this.log("show"); 27 | }; 28 | 29 | PageModule.prototype.hide = function( oPage ) { 30 | this.log("hide"); 31 | }; 32 | 33 | PageModule.prototype.destroy = function( oPage ) { 34 | this.log("destroy"); 35 | }; 36 | 37 | return PageModule; 38 | }); -------------------------------------------------------------------------------- /CognosScripts/ParamDisplay.js: -------------------------------------------------------------------------------- 1 | define( function() { 2 | "use strict"; 3 | 4 | /* 5 | Module Type: Custom Control Module 6 | Purpose: Reads from sessionStorage and, for each parameter, displays the prompt name and selected values. 7 | */ 8 | 9 | var log = function (label, message) { 10 | console.log(" **** " + label + " : " + message); 11 | } 12 | 13 | function ParamDisplay() {}; 14 | 15 | ParamDisplay.prototype.initialize = function(oControlHost, fnDoneInitializing) { 16 | log("ParamDisplay", "CustomControlModule.initialize" ); 17 | 18 | this.Params = window.Application.GetParameterValues(); 19 | 20 | fnDoneInitializing(); 21 | }; 22 | 23 | ParamDisplay.prototype.destroy = function(oControlHost) { 24 | //log("ParamDisplay", "CustomControlModule.destroy" ); 25 | }; 26 | 27 | ParamDisplay.prototype.draw = function(oControlHost) { 28 | log("ParamDisplay", "CustomControlModule.draw" ); 29 | 30 | var tbl = document.createElement("table"); 31 | this.Params.forEach(function(e) { 32 | var tr = document.createElement("tr"); 33 | var paramName = document.createElement("td"); 34 | paramName.appendChild(document.createTextNode(e.name)); 35 | paramName.style.verticalAlign = "top"; 36 | tr.appendChild(paramName); 37 | var paramValue = document.createElement("td"); 38 | paramValue.style.verticalAlign = "top"; 39 | var ParamValue = ""; 40 | //var paramDiv = document.createElement("div"); 41 | var bRange = false; 42 | e.value.forEach(function(v) { 43 | if (v.type.indexOf("Range") != -1) { 44 | bRange = true; 45 | var paramDiv = document.createElement("div"); 46 | ParamValue = ((typeof v.start == "undefined") ? "" : v.start.display) + " to " + ((typeof v.end == "undefined") ? "" : v.end.display); 47 | paramDiv.appendChild(document.createTextNode(ParamValue)); 48 | paramValue.appendChild(paramDiv); 49 | } 50 | else { 51 | ParamValue += ", " + ((typeof v.display == "undefined") ? "" : v.display); 52 | } 53 | }); 54 | if (!bRange) paramValue.appendChild(document.createTextNode(ParamValue.substring(2))); 55 | tr.appendChild(paramValue); 56 | tbl.appendChild(tr); 57 | }); 58 | oControlHost.container.appendChild(tbl); 59 | }; 60 | 61 | ParamDisplay.prototype.show = function(oControlHost) { 62 | //log("ParamDisplay", "CustomControlModule.show" ); 63 | }; 64 | 65 | ParamDisplay.prototype.hide = function(oControlHost) { 66 | //log("ParamDisplay", "CustomControlModule.hide" ); 67 | }; 68 | 69 | ParamDisplay.prototype.isInValidState = function(oControlHost) { 70 | //log("ParamDisplay", "CustomControlModule.isInValidState" ); 71 | }; 72 | 73 | ParamDisplay.prototype.getParameters = function(oControlHost) { 74 | //log("ParamDisplay", "CustomControlModule.getParameters" ); 75 | }; 76 | 77 | ParamDisplay.prototype.setData = function(oControlHost, oDataStore) { 78 | //log("ParamDisplay", "CustomControlModule.setData" ); 79 | }; 80 | 81 | return ParamDisplay; 82 | }); -------------------------------------------------------------------------------- /CognosScripts/ParameterCapture.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | "use strict"; 3 | 4 | /* 5 | Module Type: Page Module 6 | Purpose: Captures parameter name, prompt name, and selected 7 | parameter values. 8 | Stores data in sessionStorage for retrieval by the 9 | next prompt page using this module or a custom control 10 | using the ParameterDisplay Custom Control Module. 11 | Requirements: The first prompt page must have a layout calculation 12 | named "ReportName" defined as ReportName() 13 | Future: This functionality should probably be incorporated 14 | into Prompts.js. 15 | */ 16 | 17 | var log = function (label, message) { 18 | console.log(" **** " + label + " : " + message); 19 | } 20 | 21 | function PageModule() { 22 | }; 23 | 24 | PageModule.prototype.load = function(oPage) { 25 | log("page", "PageModule.load" ); 26 | 27 | var crObject = oPage.getControlByName("ReportName"); 28 | //this.CurrentReport = ""; 29 | this.CurrentReport = sessionStorage.getItem("CurrentReport"); 30 | if (crObject) { 31 | this.CurrentReport = crObject.text; 32 | sessionStorage.setItem("CurrentReport", this.CurrentReport); 33 | } 34 | 35 | //var apc = oPage.getAllPromptControls(); 36 | // 37 | //apc.forEach(function (n) { 38 | // log(" Prompts: ", n.name); 39 | //}); 40 | }; 41 | 42 | PageModule.prototype.show = function(oPage) { 43 | log("page", "PageModule.show" ); 44 | }; 45 | 46 | PageModule.prototype.hide = function(oPage) { 47 | log("page", "PageModule.hide" ); 48 | }; 49 | 50 | PageModule.prototype.destroy = function(oPage) { 51 | log("page", "PageModule.destroy" ); 52 | 53 | if (this.CurrentReport) { 54 | if (!sessionStorage.getItem("Parameters" + this.CurrentReport)) { 55 | sessionStorage.setItem("Parameters" + this.CurrentReport, JSON.stringify({})); 56 | } 57 | 58 | var prompts = oPage.getAllPromptControls(); 59 | prompts.forEach(function (e) { 60 | var p = JSON.parse(sessionStorage.getItem("Parameters" + this.CurrentReport)); 61 | var v1 = e.getValues(); 62 | var v2 = JSON.stringify(v1); 63 | var v3 = e.name; 64 | var v4 = [v3, v2]; 65 | p[e.parameter] = JSON.stringify(v4); 66 | //p[e.parameter] = JSON.stringify([e.name, JSON.stringify(e.getValues())]); 67 | sessionStorage.setItem("Parameters" + this.CurrentReport, JSON.stringify(p)); 68 | }, this); 69 | } 70 | }; 71 | 72 | return PageModule; 73 | }); -------------------------------------------------------------------------------- /CognosScripts/ParameterDisplay.js: -------------------------------------------------------------------------------- 1 | define( function() { 2 | "use strict"; 3 | 4 | /* 5 | Module Type: Custom Control Module 6 | Purpose: Reads from sessionStorage and, for each parameter, displays the prompt name and selected values. 7 | */ 8 | 9 | var log = function (label, message) { 10 | console.log(" **** " + label + " : " + message); 11 | } 12 | 13 | function ParameterDisplay() {}; 14 | 15 | ParameterDisplay.prototype.initialize = function(oControlHost, fnDoneInitializing) { 16 | log("ParameterDisplay", "CustomControlModule.initialize" ); 17 | this.CurrentReport = sessionStorage.getItem("CurrentReport"); 18 | fnDoneInitializing(); 19 | }; 20 | 21 | ParameterDisplay.prototype.destroy = function(oControlHost) { 22 | log("ParameterDisplay", "CustomControlModule.destroy" ); 23 | }; 24 | 25 | ParameterDisplay.prototype.draw = function(oControlHost) { 26 | log("ParameterDisplay", "CustomControlModule.draw" ); 27 | 28 | if (this.CurrentReport) { // if there is no object named ReportName, don't try to display parameters 29 | var params = JSON.parse(sessionStorage.getItem("Parameters" + this.CurrentReport)); 30 | 31 | Object.keys(params).forEach(function(e) { 32 | var ss = JSON.parse(params[e]); 33 | var ne = document.createElement("div"); 34 | var ns = ""; 35 | JSON.parse(ss[1]).forEach(function(f) { 36 | if (f.start) { 37 | ns += ", start: " + ((typeof f.start.display == "undefined") ? "" : f.start.display) + ", end: " + ((typeof f.end.display == "undefined") ? "" : f.end.display); 38 | } 39 | else { 40 | ns += ", " + ((typeof f.display == "undefined") ? "" : f.display); 41 | } 42 | }); 43 | ns = ns.substring(2); 44 | var nc = document.createTextNode(ss[0] + ": " + ns); 45 | ne.appendChild(nc); 46 | oControlHost.container.appendChild(ne); 47 | }); 48 | } 49 | 50 | //oControlHost.container.innerHTML = JSON.stringify(apn); 51 | }; 52 | 53 | ParameterDisplay.prototype.show = function(oControlHost) { 54 | log("ParameterDisplay", "CustomControlModule.show" ); 55 | }; 56 | 57 | ParameterDisplay.prototype.hide = function(oControlHost) { 58 | log("ParameterDisplay", "CustomControlModule.hide" ); 59 | }; 60 | 61 | ParameterDisplay.prototype.isInValidState = function(oControlHost) { 62 | log("ParameterDisplay", "CustomControlModule.isInValidState" ); 63 | }; 64 | 65 | ParameterDisplay.prototype.getParameters = function(oControlHost) { 66 | log("ParameterDisplay", "CustomControlModule.getParameters" ); 67 | }; 68 | 69 | ParameterDisplay.prototype.setData = function(oControlHost, oDataStore) { 70 | log("ParameterDisplay", "CustomControlModule.setData" ); 71 | }; 72 | 73 | return ParameterDisplay; 74 | }); -------------------------------------------------------------------------------- /CognosScripts/ParameterToText.js: -------------------------------------------------------------------------------- 1 | define (["/CognosScripts/json.js", "/CognosScripts/xml2json.js", "/CognosScripts/cleanParams.js"], function () { 2 | /* 3 | author: doug pulse 4 | created: 2016-05-13 5 | license: public domain 6 | 7 | input: object parameter name/value pairs returned by cleanParams 8 | 9 | output: string something more useful for reporting 10 | 11 | purpose: Convert a list of parameter values stored as a javascript 12 | object into a string. 13 | 14 | usage: After converting the parameter data from the original XML in 15 | databaseserver.IBMCognosAudit.COGIPF_PARAMETER.COGIPF_PARAMETER_VALUE_BLOB 16 | to a JSON string, the resulting JSON can be parsed (JSON.parse) 17 | into an object and used as input to these functions. 18 | 19 | This function expects a single value from a single audit record. The 20 | custom control for this script should be in a list column body. The 21 | master-detail relationships property of the data set should be set to 22 | join to the main data set on COGIPF_SUBREQUESTID so that each custom 23 | control receives only one value from the COGIPF_PARAMETER_VALUE_BLOB column. 24 | */ 25 | 26 | 27 | var log = function (label, message) { 28 | console.log(" **** " + label + " : " + message); 29 | } 30 | 31 | ParameterDisplayValues = function (o) { 32 | var sOut = ""; 33 | var vals = []; 34 | for (var a in o) { 35 | //alert(a); 36 | sOut += a; 37 | vals = []; 38 | if (o[a][0].start) { 39 | sOut += " in range {"; 40 | for (var i = 0; i < o[a].length; i++) { 41 | vals.push(o[a][i].start.display + " to " + o[a][i].end.display); 42 | } 43 | } 44 | else { 45 | sOut += " = {"; 46 | for (var i = 0; i < o[a].length; i++) { 47 | vals.push(o[a][i].display); 48 | } 49 | } 50 | sOut += vals.toString() + "}\n"; 51 | } 52 | return sOut; 53 | } 54 | 55 | //ParameterValues = function (o) { 56 | // var sOut = ""; 57 | // var vals = []; 58 | // for (var a in o) { 59 | // //alert(a); 60 | // sOut += a; 61 | // vals = []; 62 | // if (o[a][0].start) { 63 | // sOut += " in range {"; 64 | // for (var i = 0; i < o[a].length; i++) { 65 | // vals.push(o[a][i].start.use + " to " + o[a][i].end.use); 66 | // } 67 | // } 68 | // else { 69 | // sOut += " = {"; 70 | // for (var i = 0; i < o[a].length; i++) { 71 | // vals.push(o[a][i].use); 72 | // } 73 | // } 74 | // sOut += vals.toString() + "}\n"; 75 | // } 76 | // return sOut; 77 | //} 78 | 79 | 80 | 81 | 82 | function ParameterToText() { 83 | }; 84 | 85 | ParameterToText.prototype.initialize = function( oControlHost, fnDoneInitializing ) { 86 | log("ParameterToText", "Control.initialize" ); 87 | fnDoneInitializing(); 88 | }; 89 | 90 | ParameterToText.prototype.draw = function( oControlHost ) { 91 | log("ParameterToText", "Control.draw" ); 92 | var o = oControlHost.configuration; 93 | this.colName = ( o && o.colName ) ? o.colName : "Parameter XML"; 94 | 95 | //log("Parameter XML", this.xml); 96 | var j = xml2json(this.xml); // returns a string 97 | var o = JSON.parse(j); // returns an object 98 | var c = cleanParams(o); // returns 99 | var s = ParameterDisplayValues(c); 100 | //return s.replace(/\n/gi, "<br />"); 101 | 102 | var f = document.createElement("span"); 103 | f.innerHTML = s.replace(/\n/gi, "
"); 104 | 105 | oControlHost.container.appendChild(f); 106 | }; 107 | 108 | ParameterToText.prototype.setData = function( oControlHost, oDataStore ) { 109 | log("ParameterToText", "Control.setData" ); 110 | log("ParameterToText", "Control.draw" ); 111 | var o = oControlHost.configuration; 112 | this.colName = ( o && o.colName ) ? o.colName : "Parameter XML"; 113 | var colNum = oDataStore.getColumnIndex(this.colName); 114 | console.log(" subrequest id = " + oDataStore.getCellValue(0, oDataStore.getColumnIndex("Subrequest ID"))); 115 | this.xml = oDataStore.getCellValue(0, colNum); 116 | }; 117 | 118 | return ParameterToText; 119 | }); 120 | -------------------------------------------------------------------------------- /CognosScripts/PromptAutoFinish.js: -------------------------------------------------------------------------------- 1 | define( function() { 2 | "use strict"; 3 | 4 | var log = function (label, message) { 5 | console.log(" **** " + label + " : " + message); 6 | }; 7 | 8 | function AutoFinish() { 9 | }; 10 | 11 | AutoFinish.prototype.initialize = function( oControlHost, fnDoneInitializing ) { 12 | log("AutoFinish", "Control.initialize" ); 13 | if (!oControlHost.page.AutoFinish) { 14 | console.log(" Defining AutoFinish"); 15 | oControlHost.page.AutoFinish = function () { 16 | oControlHost.next() 17 | }; 18 | } 19 | fnDoneInitializing(); 20 | }; 21 | 22 | AutoFinish.prototype.draw = function( oControlHost ) { 23 | log("AutoFinish", "Control.draw" ); 24 | }; 25 | 26 | return AutoFinish; 27 | }); -------------------------------------------------------------------------------- /CognosScripts/PromptButton.js: -------------------------------------------------------------------------------- 1 | define( function() { 2 | "use strict"; 3 | 4 | var log = function (label, message) { 5 | console.log(" **** PromptButton : " + label + " : " + message); 6 | }; 7 | 8 | 9 | function Button() { 10 | }; 11 | 12 | 13 | Button.prototype.initialize = function( oControlHost, fnDoneInitializing ) { 14 | log("Button", "Control.initialize" ); 15 | 16 | /* 17 | Configuration: 18 | { 19 | "ButtonType": "Finish", 20 | "ButtonLabel": "Finish", 21 | "RequiredPrompts": // this is [ [a and b] or [a and c] ] 22 | [ 23 | ["WorkOrder", "Bien"], 24 | ["WorkOrder", "fy"] 25 | ], 26 | "RequiredPromptCount": 2, 27 | "HiddenPrompt": "MyHiddenPrompt", 28 | "ValidationFailureAlert": "validation failed" 29 | } 30 | */ 31 | 32 | /* 33 | Using RequiredPrompts or RequiredPromptCount probably only makes 34 | sense with a ButtonType of Finish or Next. 35 | 36 | Using HiddenPrompt is for when the page may already have all 37 | required prompts set, but you want to allow autosubmit to control 38 | other prompting and not to "finish" prompting. 39 | The prompt used for HiddenPrompt should be a Text Box Prompt. 40 | */ 41 | 42 | this.controlHost = oControlHost; 43 | this.oConfig = this.controlHost.configuration; 44 | this.page = this.controlHost.page; 45 | this.Prompts = this.page.getAllPromptControls(); 46 | this.ButtonType = ( this.oConfig && this.oConfig.ButtonType ) ? this.oConfig.ButtonType : "Finish"; 47 | this.ButtonLabel = ( this.oConfig && this.oConfig.ButtonLabel ) ? this.oConfig.ButtonLabel : this.ButtonType; 48 | this.failureAlert = ( this.oConfig && this.oConfig.ValidationFailureAlert ) ? this.oConfig.ValidationFailureAlert : null; 49 | 50 | this.RequiredPromptsValidator = function (arr) { 51 | //[ 52 | // ["WorkOrder", "Bien"], 53 | // ["WorkOrder", "fy"] 54 | //] 55 | var valid = false; 56 | var v; // prompt values 57 | 58 | for (var i = 0; i < arr.length; i++) { 59 | var m = 0; 60 | for (var j = 0; j < arr[i].length; j++) { 61 | if (this.page.getControlByName(arr[i][j])) { 62 | v = this.page.getControlByName(arr[i][j]).getValues(); 63 | // A single-select textbox prompt is a special case. 64 | // If it is empty, getValues() returns an array with one element: 65 | // [{"use":null,"display":null}] 66 | if (v.length == 1 && (v[0].use == "" || v[0].use == undefined) && (v[0].display == null || v[0].display == "" || v[0].display == undefined)) { 67 | } 68 | else if (v.length > 0) { 69 | m++; 70 | } 71 | } 72 | } 73 | if (m == j) { 74 | valid = true; 75 | break; 76 | } 77 | } 78 | return valid; 79 | }; 80 | 81 | this.RequiredPromptCountValidator = function (n) { 82 | var m = 0; // How many prompts have values? 83 | var v; // prompt values 84 | 85 | if (n < 1) return true; // No prompts are required. Why use this feature? 86 | 87 | for (var i = 0; i < this.Prompts.length && m < n; i++) { 88 | if (this.Prompts[i].name.substr(0, 4) == 'oper') { 89 | // this is an operator selector 90 | // don't count this in fulfilling a minimum number of parameters 91 | } 92 | else { 93 | v = this.Prompts[i].getValues(); 94 | // A single-select textbox prompt is a special case. 95 | // If it is empty, getValues() returns an array with one element: 96 | // [{"use":null,"display":null}] 97 | if (v.length == 1 && v[0].use == null && v[0].display == null) { 98 | } 99 | else if (v.length > 0) { 100 | m++; 101 | } 102 | } 103 | } 104 | 105 | return m >= n; 106 | }; 107 | 108 | this.CompletePromptInit = function (s) { 109 | var done = false; 110 | var p; 111 | 112 | log("CompletePromptInit", s); 113 | 114 | p = this.page.getControlByName(s) 115 | 116 | if (p) { 117 | p.setValues([{"use": undefined, "display": undefined}]); 118 | done = true; 119 | log("CompletePromptInit", "success"); 120 | } 121 | else { 122 | done = false; 123 | log("CompletePromptInit", "failure"); 124 | } 125 | 126 | return done; 127 | }; 128 | 129 | this.CompletePrompt = function (s) { 130 | var done = false; 131 | var p; 132 | 133 | log("CompletePrompt", s); 134 | 135 | p = this.page.getControlByName(s) 136 | 137 | if (p) { 138 | p.setValues([{"use": "a", "display": "a"}]); 139 | done = true; 140 | log("CompletePrompt", "success"); 141 | } 142 | else { 143 | done = false; 144 | log("CompletePrompt", "failure"); 145 | } 146 | 147 | return done; 148 | }; 149 | 150 | this.TakeAction = function () { 151 | var i = 0; 152 | var msg = ""; 153 | 154 | if (this.oConfig && this.oConfig.RequiredPrompts) { 155 | if (this.RequiredPromptsValidator(this.oConfig.RequiredPrompts)) i++; 156 | else msg += "\r\n The required parameters were not specified."; 157 | } 158 | else { 159 | i++; 160 | } 161 | 162 | if (this.oConfig && this.oConfig.RequiredPromptCount) { 163 | if (this.RequiredPromptCountValidator(this.oConfig.RequiredPromptCount)) i++; 164 | else msg += "\r\n Not enough parameters were specified."; 165 | } 166 | else { 167 | i++; 168 | } 169 | 170 | if (this.oConfig && this.oConfig.HiddenPrompt) { 171 | if (this.CompletePrompt(this.oConfig.HiddenPrompt)) i++; 172 | else msg += "\r\n Prompt named " + this.oConfig.HiddenPrompt + " was not found or could not be set."; 173 | } 174 | else { 175 | i++; 176 | } 177 | 178 | if (i == 3) { 179 | // passed validation. take action 180 | switch (this.ButtonType.toLowerCase()) { 181 | case "finish": 182 | this.controlHost.finish() 183 | break; 184 | case "next": 185 | this.controlHost.next() 186 | break; 187 | case "back": 188 | this.controlHost.back() 189 | break; 190 | case "reprompt": 191 | this.controlHost.reprompt() 192 | break; 193 | case "cancel": 194 | this.controlHost.cancel() 195 | break; 196 | default: 197 | // error 198 | } 199 | } 200 | else { 201 | // failed validation. do nothing? alert the user? write to the console? 202 | log("Prompt Validation Failure", "Unable to use the " + this.ButtonType.toUpperCase() + " feature because prompt validation failed." + msg); 203 | if (this.failureAlert) alert(this.failureAlert); 204 | } 205 | }; 206 | 207 | if (this.oConfig && this.oConfig.HiddenPrompt) { 208 | if (this.CompletePromptInit(this.oConfig.HiddenPrompt)) { 209 | } 210 | else { 211 | log("Prompt Validation Failure", "Unable to initialize.\r\n Prompt named " + this.oConfig.HiddenPrompt + " was not found or could not be set."); 212 | } 213 | } 214 | 215 | fnDoneInitializing(); 216 | }; 217 | 218 | Button.prototype.draw = function( oControlHost ) { 219 | log("Button", "Control.draw" ); 220 | 221 | //var d = document.createElement("div"); 222 | // d.className = "clsPromptComponent"; 223 | // d.setAttribute("pt", "btn"); 224 | var b = document.createElement("button"); 225 | b.className = "bp"; 226 | b.type = "button"; 227 | b.onmouseover = function () {this.className = 'bp bph'}; 228 | b.onmouseout = function () {this.className = 'bp'}; 229 | b.onclick = this.TakeAction.bind(this); 230 | b.innerHTML = this.ButtonLabel; 231 | oControlHost.container.appendChild(b); 232 | //d.appendChild(b); 233 | //oControlHost.container.appendChild(d); 234 | }; 235 | 236 | return Button; 237 | }); -------------------------------------------------------------------------------- /CognosScripts/PromptDateDefault.js: -------------------------------------------------------------------------------- 1 | define(function() { 2 | "use strict"; 3 | /* 4 | Sets a date prompt to the value(s) returned by a query. 5 | 6 | The query may return a list of single dates or a list of start and end dates. 7 | 8 | Sample Configurations: 9 | { 10 | "PromptName": "PromptDate", 11 | "Date": "Date" 12 | } 13 | { 14 | "PromptName": "PromptDate", 15 | "StartDate": "StartDate", 16 | "EndDate": "EndDate" 17 | } 18 | 19 | The data store must contain columns with names that match the values for 20 | either Date or StartDate and EndDate. 21 | The date values must be in the format yyyy-mm-dd. 22 | */ 23 | 24 | var log = function (label, message) { 25 | console.log(" **** " + label + " : " + message); 26 | }; 27 | 28 | function DateDefault() {}; 29 | 30 | DateDefault.prototype.initialize = function( oControlHost, fnDoneInitializing ) { 31 | log("DateDefault", "Control.initialize" ); 32 | 33 | var o = oControlHost.configuration; 34 | var sPromptName = o && o["PromptName"] ? o["PromptName"] : null; 35 | var ctrl = oControlHost.page.getControlByName(sPromptName); 36 | var datastores = oControlHost.control.dataStores ? oControlHost.control.dataStores : null; 37 | var sDateColumn = o && o["Date"] ? o["Date"] : null; 38 | var sStartDateColumn = o && o["StartDate"] ? o["StartDate"] : null; 39 | var sEndDateColumn = o && o["EndDate"] ? o["EndDate"] : null; 40 | var bValid = true; 41 | var reDate = /^\d{4}-\d{2}-\d{2}$/; 42 | var iDateCol, iStartDateCol, iEndDateCol; 43 | var sDate, sStartDate, sEndDate; 44 | var sMsg = ""; 45 | 46 | 47 | // check configuration 48 | if (!sPromptName) { 49 | bValid = false; 50 | sMsg += "Invalid Configuration: The name of the date prompt was not provided."; 51 | } 52 | 53 | if (!sDateColumn && !(sStartDateColumn || sEndDateColumn)) { 54 | bValid = false; 55 | sMsg += "Invalid Configuration: The name of either the date prompt or the startdate and enddate prompts are required."; 56 | } 57 | 58 | if (!ctrl) { 59 | bValid = false; 60 | sMsg += "Invalid configuration: "; 61 | if (o["PromptName"]) { 62 | sMsg += " There is not a prompt named '" + o["PromptName"] + "'."; 63 | } 64 | else { 65 | sMsg += " There is not a prompt named 'PromptDate' and no prompt name was provided in the configuration."; 66 | } 67 | } 68 | 69 | if (!datastores || datastores.length != 1) { 70 | bValid = false; 71 | sMsg += "Invalid configuration: The DateDefault custom control requires one data store."; 72 | } 73 | 74 | if (!bValid) { 75 | log("DateDefault", sMsg); 76 | return; 77 | } 78 | 79 | // check data store(s) 80 | var ds = datastores[0]; 81 | var bDateFound = false; 82 | var bStartDateFound = false; 83 | var bEndDateFound = false; 84 | 85 | for (var i = 0; i < ds.columnNames.length; i++) { 86 | if (sDateColumn) { 87 | if (ds.columnNames[i] == sDateColumn) { 88 | iDateCol = i; 89 | bDateFound = true; 90 | break; 91 | } 92 | } 93 | else { 94 | if (ds.columnNames[i] == sStartDateColumn) { 95 | iStartDateCol = i; 96 | bStartDateFound = true; 97 | } 98 | if (ds.columnNames[i] == sEndDateColumn) { 99 | iEndDateCol = i; 100 | bEndDateFound = true; 101 | } 102 | if (bStartDateFound && bEndDateFound) break; 103 | } 104 | } 105 | 106 | bValid = (sDateColumn && bDateFound) || (!sDateColumn && bStartDateFound && bEndDateFound); 107 | 108 | if (!bValid) { 109 | log("DateDefault", "The date columns defined in the configurations were not found in the data store."); 110 | return; 111 | } 112 | 113 | 114 | // It's all good. Let's get the data and validate it. 115 | var vals = ds.columnValues; 116 | if (sDateColumn) { 117 | for (var i = 0; i < ds.rowCount; i++) { 118 | if (!vals[iDateCol][i].substr(0, 10).match(reDate)) { 119 | sMsg += "Invalid input: " + vals[iDateCol][i] + " is not a valid date."; 120 | bValid = false; 121 | break; 122 | } 123 | } 124 | } 125 | else { 126 | for (var i = 0; i < ds.rowCount; i++) { 127 | if (!vals[iStartDateCol][i].substr(0, 10).match(reDate)) { 128 | sMsg += "Invalid input: " + vals[iStartDateCol][i] + " is not a valid date."; 129 | bValid = false; 130 | break; 131 | } 132 | if (!vals[iEndDateCol][i].substr(0, 10).match(reDate)) { 133 | sMsg += "Invalid input: " + vals[iEndDateCol][i] + " is not a valid date."; 134 | bValid = false; 135 | break; 136 | } 137 | } 138 | } 139 | 140 | if (!bValid) { 141 | log("DateDefault", sMsg); 142 | return; 143 | } 144 | 145 | 146 | // Data's good. Build the array and add it to the control. 147 | var arrDates = []; 148 | if (sDateColumn) { 149 | for (var i = 0; i < ds.rowCount; i++) { 150 | arrDates.push({"use":vals[iDateCol][i].substr(0, 10)}); 151 | } 152 | } 153 | else { 154 | for (var i = 0; i < ds.rowCount; i++) { 155 | arrDates.push({"start":{"use":vals[iStartDateCol][i].substr(0, 10)},"end":{"use":vals[iEndDateCol][i].substr(0, 10)}}); 156 | } 157 | } 158 | oControlHost.page.getControlByName(sPromptName).setValues(arrDates); 159 | 160 | 161 | fnDoneInitializing(); 162 | }; 163 | 164 | DateDefault.prototype.draw = function( oControlHost ) 165 | { 166 | 167 | }; 168 | 169 | return DateDefault; 170 | }); 171 | 172 | 173 | /* 174 | Simple values 175 | { 'use': '[a].[b].[c]', 'display': 'Canada' } 176 | 177 | Range values 178 | { 179 | 'start': {'use': '2007-01-01', 'display': 'January 1, 2007'} 180 | 'end': {'use': '2007-12-31', 'display': 'December 31, 2007'} 181 | } 182 | 183 | Multiple values 184 | [ 185 | { 'use': '12', 'display': 'Canada' }, 186 | { 'use': '41', 'display': 'Germany' }, 187 | { 'use': '76', 'display': 'Japan' } 188 | ] 189 | */ -------------------------------------------------------------------------------- /CognosScripts/PromptFinish.js: -------------------------------------------------------------------------------- 1 | define( function() { 2 | "use strict"; 3 | 4 | /* 5 | Sample Configuration: 6 | RequiredPrompts and RequiredPromptCount do not need to be used together. 7 | In this example, Country and City are optional prompts (and filters). 8 | Since this does not use prompt validation, requiring year is meaningless. 9 | Even if the Required property is Yes, it must still be specified in the 10 | configuration for the custom control. If it is not, a system-generated 11 | prompt page will appear after the user clicks on the custom prompt button. 12 | 13 | { 14 | "name": "FinnishButton", 15 | "buttonLabel": "Finish", 16 | "RequiredPrompts": 17 | [ 18 | ["Country","Year"], 19 | ["City","Year"] 20 | ], 21 | "RequiredPromptCount":2 22 | } 23 | */ 24 | 25 | var log = function (label, message) { 26 | console.log(" **** " + label + " : " + message); 27 | } 28 | 29 | function customFinish(){}; 30 | 31 | customFinish.prototype.draw = function( oControlHost ) { 32 | //log("draw", "start"); 33 | //this.m_sName = oControlHost.configuration.name || "FinishButton"; 34 | this.msg = ""; 35 | 36 | var o = oControlHost.configuration 37 | , buttonLabel = o["buttonLabel"] ? o["buttonLabel"] : 'Finish' 38 | , el = oControlHost.container; 39 | 40 | el.innerHTML = '' + 41 | '' ; 42 | 43 | document.getElementById("custom_PromptFinish").onmouseover = this.AddClass.bind (this, oControlHost, el.querySelector( "#custom_PromptFinish" ), "bph"); 44 | document.getElementById("custom_PromptFinish").onmouseout = this.RemoveClass.bind (this, oControlHost, el.querySelector( "#custom_PromptFinish" ), "bph"); 45 | 46 | document.getElementById("custom_PromptFinish").onclick = this.Finish.bind(this, oControlHost); 47 | //log("draw", "complete"); 48 | }; 49 | 50 | customFinish.prototype.Finish = function (oControlHost) { 51 | //log("Finish", "start"); 52 | 53 | if (this.checkPrompts(oControlHost)) { 54 | oControlHost.finish(); 55 | } 56 | else { 57 | alert(this.msg); 58 | } 59 | }; 60 | 61 | customFinish.prototype.checkPrompts = function(oControlHost) { 62 | //log("checkPrompts", "start"); 63 | var o = oControlHost.configuration; 64 | 65 | var blnGood = false; 66 | 67 | if (o.RequiredPrompts && o.RequiredPromptCount) { 68 | blnGood = this.RequiredPrompts(o.RequiredPrompts, oControlHost) && this.RequiredPromptCount(o.RequiredPromptCount, oControlHost); 69 | } 70 | else { 71 | if (o.RequiredPrompts) { 72 | blnGood = this.RequiredPrompts(o.RequiredPrompts, oControlHost); 73 | } 74 | if (o.RequiredPromptCount) { 75 | blnGood = this.RequiredPromptCount(o.RequiredPromptCount, oControlHost); 76 | } 77 | } 78 | 79 | return blnGood; 80 | }; 81 | 82 | customFinish.prototype.RequiredPrompts = function (rp, oControlHost) { 83 | //log("RequiredPrompts", "start"); 84 | var blnGood = false; 85 | // check the entire set 86 | // if any group is complete, we're done 87 | rp.forEach(function (arr) { 88 | // check each group 89 | if (!blnGood) { 90 | // reset the counter 91 | var rpc = 0; 92 | arr.forEach(function(sPromptName) { 93 | //log(" prompt", sPromptName); 94 | var oPrompt = oControlHost.page.getControlByName(sPromptName); 95 | if (!oPrompt) { 96 | alert(sPromptName + " was not found."); 97 | } 98 | else { 99 | //log(" prompt value", JSON.stringify(oPrompt.getValues()[0].use)); 100 | rpc += (oPrompt.getValues()[0].use == undefined || oPrompt.getValues()[0].use == "") ? 0 : 1; 101 | } 102 | }); 103 | // if the counter grew to the size of the array, we're good 104 | //log(" array length", arr.length); 105 | //log(" prompt count", rpc); 106 | if (arr.length == rpc) blnGood = true; 107 | } 108 | }); 109 | //log("Required Prompts", blnGood); 110 | if (!blnGood) this.msg = "You must enter a valid combination of parameters." 111 | return blnGood; 112 | }; 113 | 114 | customFinish.prototype.RequiredPromptCount = function (rpc, oControlHost) { 115 | //log("RequiredPromptCount", "start"); 116 | //log(p.name, ""); 117 | var blnGood = false; 118 | var i = 0; 119 | var a = oControlHost.page.getAllPromptControls(); 120 | a.forEach(function(e) { 121 | //log(" Prompt Validation: Prompt" + e.name, JSON.stringify(e.getValues())); 122 | //log(" Prompt Validation: Prompt" + e.name, e.getValues()[0].use == undefined); 123 | i += e.getValues()[0].use == undefined ? 0 : 1; 124 | //log(" Prompt Validation: Prompt" + e.name, i); 125 | }); 126 | //log("PromptCount", i); 127 | //log("RequiredPromptCount", rpc); 128 | blnGood = i >= rpc; 129 | //log("Required Prompt Count", blnGood); 130 | if (!blnGood) this.msg = "You must enter at least " + rpc + " parameters to proceed!"; 131 | return blnGood; 132 | }; 133 | 134 | customFinish.prototype.AddClass = function (oControlHost, o, c) { 135 | //log("AddClass", "start"); 136 | if (this.checkPrompts(oControlHost)) { 137 | o.classList.add(c); 138 | } 139 | }; 140 | 141 | customFinish.prototype.RemoveClass = function (oControlHost, o, c) { 142 | //log("RemoveClass", "start"); 143 | o.classList.remove(c); 144 | }; 145 | 146 | return customFinish; 147 | }); -------------------------------------------------------------------------------- /CognosScripts/PromptIncrementAndRun.js: -------------------------------------------------------------------------------- 1 | define( function() { 2 | "use strict"; 3 | 4 | var log = function (label, message) { 5 | console.log(" **** " + label + " : " + message); 6 | }; 7 | 8 | function Button() { 9 | }; 10 | 11 | 12 | Button.prototype.initialize = function( oControlHost, fnDoneInitializing ) { 13 | /* 14 | Configuration: 15 | { 16 | "ButtonLabel": "Increment Day Number", 17 | "PromptName": "DayNumberPrompt" 18 | } 19 | */ 20 | 21 | this.controlHost = oControlHost; 22 | this.oConfig = this.controlHost.configuration; 23 | this.page = this.controlHost.page; 24 | this.PromptName = ( this.oConfig && this.oConfig.PromptName ) ? this.oConfig.PromptName : "Prompt1"; 25 | this.ButtonLabel = ( this.oConfig && this.oConfig.ButtonLabel ) ? this.oConfig.ButtonLabel : "Finish"; 26 | this.Prompt = this.page.getControlByName(this.PromptName); 27 | this.DayNum = this.Prompt.getValues(); 28 | // You may want to verify that DayNum is a number. 29 | // Here I just check to see if it is blank and set a default value if it is. 30 | if (typeof this.DayNum[0].use == "undefined") this.DayNum = [{"use": "1", "display": "1"}]; 31 | 32 | this.TakeAction = function () { 33 | this.DayNum[0].use = ((this.DayNum[0].use * 1.0) + 1).toString(); 34 | this.DayNum[0].display = ((this.DayNum[0].display * 1.0) + 1).toString(); 35 | this.Prompt.setValues(this.DayNum); 36 | this.controlHost.finish(); 37 | }; 38 | 39 | fnDoneInitializing(); 40 | }; 41 | 42 | Button.prototype.draw = function( oControlHost ) { 43 | var b = document.createElement("button"); 44 | b.className = "bp"; 45 | b.type = "button"; 46 | b.onmouseover = function () {this.className = 'bp bph'}; 47 | b.onmouseout = function () {this.className = 'bp'}; 48 | b.onclick = this.TakeAction.bind(this); 49 | b.innerHTML = this.ButtonLabel; 50 | oControlHost.container.appendChild(b); 51 | }; 52 | 53 | return Button; 54 | }); 55 | -------------------------------------------------------------------------------- /CognosScripts/PromptLoadValuesFromQuery.js: -------------------------------------------------------------------------------- 1 | define( function() { 2 | "use strict"; 3 | 4 | /* 5 | Add data sets to the control. 6 | Add one query item to Categories. 7 | Name the data set the same as the target prompt. 8 | Ensure the custom control appears after the prompt in the layout. 9 | The query output in the data set will appear in the prompt. 10 | 11 | Tested with multi-select textbox prompts. 12 | */ 13 | 14 | var log = function (name, label, message) { 15 | console.log(" **** " + name + " : " + label + " : " + message); 16 | }; 17 | 18 | var convertValues = function (valArray) { 19 | var a = []; 20 | valArray.forEach(function (n) { 21 | a.push({"use": n, "display": n}); 22 | }); 23 | return a; 24 | }; 25 | 26 | function loadFromQuery(){}; 27 | 28 | 29 | loadFromQuery.prototype.initialize = function( oControlHost, fnDoneInitializing ) { 30 | log(oControlHost.control.name, "initialize", "start"); 31 | 32 | this.vals = []; 33 | 34 | fnDoneInitializing(); 35 | log(oControlHost.control.name, "initialize", "complete"); 36 | }; 37 | 38 | loadFromQuery.prototype.draw = function( oControlHost ) { 39 | log(oControlHost.control.name, "draw", "start"); 40 | 41 | var o = oControlHost.configuration; 42 | var oPage = oControlHost.page; 43 | for (var e in this.vals) { 44 | var oPrompt = oPage.getControlByName(this.vals[e].name); 45 | oPrompt.setValues(convertValues(this.vals[e].values)); 46 | } 47 | 48 | log(oControlHost.control.name, "draw", "complete"); 49 | }; 50 | 51 | loadFromQuery.prototype.setData = function( oControlHost, oDataStore ) { 52 | log(oControlHost.control.name, "setData:" + oDataStore.name, "start"); 53 | 54 | this.m_oDataStore = oDataStore; 55 | this.m_aData = []; 56 | var iRowCount = oDataStore.rowCount; 57 | for ( var iRow = 0; iRow < iRowCount; iRow++ ) { 58 | this.m_aData.push(oDataStore.getCellValue( iRow, 0 )); 59 | } 60 | 61 | if (this.m_aData.length) { 62 | this.m_aData.sort(); 63 | 64 | var thisPrompt = {} 65 | thisPrompt.name = oDataStore.name; 66 | thisPrompt.values = this.m_aData.slice(); 67 | this.vals.push(thisPrompt); 68 | } 69 | 70 | log(oControlHost.control.name, "setData:" + oDataStore.name, "complete"); 71 | }; 72 | 73 | return loadFromQuery; 74 | }); 75 | 76 | 77 | -------------------------------------------------------------------------------- /CognosScripts/README.md: -------------------------------------------------------------------------------- 1 | # CognosScripts 2 | This is where I put all of the JavaScript modules. On my Cognos server, this lives at wwwroot\CognosScripts. 3 | 4 | ## Prompts.js 5 | A page module that provides various ways to control prompt behaviours. 6 | **See the comments in the code for examples for the *Configuration* object for the Custom Control Module in Cognos.** 7 | 8 | ### PromptValues 9 | Set specific values. 10 | Cognos expects parameter values to be strings. 11 | #### PromptName 12 | The *Name* property of the prompt object. 13 | #### PromptValue 14 | The value(s) 15 | #### PromptRange 16 | The range of values 17 | #### PromptRelative 18 | For dates, choose values relative to today. 19 | 20 | ### PromptIndex 21 | (not yet implemented) 22 | Set values based on their location in the list. 23 | #### PromptName 24 | The *Name* property of the prompt object. 25 | #### PromptIndex 26 | The zero-based index of the item in the list, or a word like "first" or "last". 27 | 28 | ### SelectAll 29 | A list of prompt names for which all of the values in the prompt will be selected. 30 | 31 | ### AutoComplete 32 | Automatically complete this prompt page after automatically setting prompt values. 33 | Works with a Custom Control using *PromptAutoFinish.js*. 34 | 35 | 36 | ## PromptAutoFinish.js 37 | Custom Control module that works with Prompts.js to autofinish (autonext?) a prompt page. 38 | 39 | ## PromptFinish.js 40 | Custom Control module that handles RequiredPrompts and RequiredPromptCount. This is a different take on PromptButton.js, which may work better. 41 | 42 | ## PromptButton.js 43 | Custom Control module to create a prompt button. Includes prompt control method for RequiredPrompts and RequiredPromptCount. 44 | 45 | ## PromptDateDefault.js 46 | A way to use data rather than JavaScript to choose a set of default values for a date prompt. This is an alternative to the some of the features in Prompts.js. 47 | 48 | ## ParameterCapture.js 49 | Captures parameter name, prompt name, and selected parameter values for presentation using ParameterDisplay.js. 50 | 51 | ## ParameterDisplay.js 52 | For each prompt on any prompt page, displays the prompt name and selected values. 53 | 54 | ## ParamDisplay.js 55 | For each parameter, displays the parameter name and selected values. 56 | 57 | ## ObjectMethods.js 58 | A collection of additional object methods to make some scripting tasks simpler.
Used by Prompts.js. 59 | 60 | ## HolidayCalendar.js 61 | Provides a HolidayCalendar object used by some methods of the Date object that are defined in ObjectMethods.js.
Used by Prompt.js. 62 | 63 | ## HolidayCalendarControl.js 64 | Custom Control module to define the data set for the HolidayCalendar object in Prompts.js. Used as the module for a custom control that has one dataset with one category that contains the dates of holidays appropriate to the context of the report. 65 | 66 | ## mapOpenLayers.js 67 | Provides a means to present points on a map using a base map from OpenStreetMap or ArcGISOnline. 68 | 69 | ## OrderOfMethodsPageModule.js and OrderOfMethodsCustomControl.js 70 | Used to demonstrate when events occur in the Cognos JavaScript API. 71 | 72 | ## ParameterToText.js 73 | Parses the XML stored in the COGIPF_PARAMETER_VALUE_BLOB field for paramValue records and makes them human-readable for reporting. 74 | 75 | ## cleanParams.js 76 | Used by ParameterToText.js to return the human-readable text. 77 | 78 | ## xml2json.js 79 | Used by ParameterToText.js to turn the XML into a JSON string. 80 | 81 | ## json2xml.js 82 | Not used yet. It's the inverse of xml2json.js. 83 | 84 | ## json.js 85 | Used by ParameterToText.js. Creates a JSON object only if one does not already exist. (for old browsers) 86 | 87 | -------------------------------------------------------------------------------- /CognosScripts/cleanParams.js: -------------------------------------------------------------------------------- 1 | /* 2 | author: doug pulse 3 | created: 2016-05-13 4 | license: public domain 5 | 6 | input: object the results of running xml2json on databaseserver.IBMCognosAudit.COGIPF_PARAMETER.COGIPF_PARAMETER_VALUE_BLOB 7 | 8 | output: object something smaller -- only what we actually need from the original data 9 | 10 | purpose: When a report is run in IBM Cognos BI (10.2.1, 10.2.2, 11.0.2), 11 | the system optionally* stores parameter values in the 12 | COGIPF_PARAMETER_VALUE_BLOB column of the COGIPF_PARAMETER 13 | table in the Cognos Audit database (commonly named IBMCognosAudit). 14 | databaseserver.IBMCognosAudit.COGIPF_PARAMETER.COGIPF_PARAMETER_VALUE_BLOB 15 | All of the report parameters are included in the string, 16 | regardless of whether or not they are used. It is stored as 17 | ntext, but the data is xml. After converting the xml to json 18 | (see xml2json.js), the string can be used as input for this function. 19 | cleanParams() strips the parameter data down to only what was 20 | actually used when the report was run. It also dramatically 21 | simplifies the object, removing all of the Cognos-specific 22 | stuff that no Cognos admininstrator would ever find useful. 23 | 24 | * create a custom property in the advanced properties for the 25 | Report and Batch Report services: 26 | RSVP.PARAMETERS.LOG = true 27 | */ 28 | 29 | function cleanParams (params) { 30 | var p = params.parameterValues.item; 31 | var o = new Object(); 32 | 33 | // iterate through each of the parameters recorded in the data 34 | if (p.length > 1) { 35 | for (var i = 0; i < p.length; i++) { 36 | console.log(" " + i); 37 | // look for parameters that are actually used 38 | if (p[i]["bus:value"]["@SOAP-ENC:arrayType"] != "bus:parmValueItem[0]") { 39 | // the value should not have a 0 40 | // something like "bus:parmValueItem[1]" 41 | // the number defines the length of the array of values 42 | var name = p[i]["bus:name"]["#text"]; 43 | var vals = p[i]["bus:value"]["item"]; 44 | o[name] = []; 45 | var n = p[i]["bus:value"]["@SOAP-ENC:arrayType"].replace(/bus:parmValueItem\[/gi, "").replace(/]/gi, ""); 46 | console.log(" " + n); 47 | 48 | if (n == 1) { 49 | if (vals["@xsi:type"] == "bus:boundRangeParmValueItem") { 50 | // in_range prompts are special: 51 | o[name].push({start: {display: vals["bus:start"]["bus:display"]["#text"], use: vals["bus:start"]["bus:use"]["#text"]}, "end": {display: vals["bus:end"]["bus:display"]["#text"], use: vals["bus:end"]["bus:use"]["#text"]}}); 52 | } 53 | else { 54 | try { 55 | o[name].push({display: vals["bus:display"]["#text"], use: vals["bus:use"]["#text"]}); 56 | } 57 | catch (e) { 58 | console.log(e.message); 59 | console.log(JSON.stringify(params)); 60 | } 61 | } 62 | } 63 | else { 64 | for (var j = 0; j < n; j++) { 65 | console.log(" " + j); 66 | if (vals[j]["@xsi:type"] == "bus:boundRangeParmValueItem") { 67 | // in_range prompts are special: 68 | o[name].push({start: {display: vals[j]["bus:start"]["bus:display"]["#text"], use: vals[j]["bus:start"]["bus:use"]["#text"]}, end: {display: vals[j]["bus:end"]["bus:display"]["#text"], use: vals[j]["bus:end"]["bus:use"]["#text"]}}); 69 | } 70 | else { 71 | try { 72 | o[name].push({display: vals[j]["bus:display"]["#text"], use: vals[j]["bus:use"]["#text"]}); 73 | } 74 | catch (e) { 75 | console.log(e.message); 76 | console.log(JSON.stringify(params)); 77 | } 78 | } 79 | } 80 | } 81 | } 82 | } 83 | } 84 | else { 85 | // there is only one parameter 86 | // look for parameters that are actually used 87 | if (p["bus:value"]["@SOAP-ENC:arrayType"] != "bus:parmValueItem[0]") { 88 | // the value should not have a 0 89 | // something like "bus:parmValueItem[1]" 90 | // the number defines the length of the array of values 91 | var name = p["bus:name"]["#text"]; 92 | var vals = p["bus:value"]["item"]; 93 | o[name] = []; 94 | var n = p["bus:value"]["@SOAP-ENC:arrayType"].replace(/bus:parmValueItem\[/gi, "").replace(/]/gi, ""); 95 | 96 | if (n == 1) { 97 | if (vals["@xsi:type"] == "bus:boundRangeParmValueItem") { 98 | // in_range prompts are special: 99 | o[name].push({start: {display: vals["bus:start"]["bus:display"]["#text"], use: vals["bus:start"]["bus:use"]["#text"]}, "end": {display: vals["bus:end"]["bus:display"]["#text"], use: vals["bus:end"]["bus:use"]["#text"]}}); 100 | } 101 | else { 102 | o[name].push({display: vals["bus:display"]["#text"], use: vals["bus:use"]["#text"]}); 103 | } 104 | } 105 | else { 106 | for (var j = 0; j < n; j++) { 107 | if (vals[j]["@xsi:type"] == "bus:boundRangeParmValueItem") { 108 | // in_range prompts are special: 109 | o[name].push({start: {display: vals[j]["bus:start"]["bus:display"]["#text"], use: vals[j]["bus:start"]["bus:use"]["#text"]}, end: {display: vals[j]["bus:end"]["bus:display"]["#text"], use: vals[j]["bus:end"]["bus:use"]["#text"]}}); 110 | } 111 | else { 112 | o[name].push({display: vals[j]["bus:display"]["#text"], use: vals[j]["bus:use"]["#text"]}); 113 | } 114 | } 115 | } 116 | } 117 | } 118 | 119 | // return the cleaned parameter value data 120 | return o; 121 | } 122 | -------------------------------------------------------------------------------- /CognosScripts/json2xml.js: -------------------------------------------------------------------------------- 1 | /* This work is licensed under Creative Commons GNU LGPL License. 2 | 3 | License: http://creativecommons.org/licenses/LGPL/2.1/ 4 | Version: 0.9 5 | Author: Stefan Goessner/2006 6 | Web: http://goessner.net/ 7 | */ 8 | function json2xml(o, tab) { 9 | var toXml = function(v, name, ind) { 10 | var xml = ""; 11 | if (v instanceof Array) { 12 | for (var i=0, n=v.length; i" : "/>"; 25 | if (hasChild) { 26 | for (var m in v) { 27 | if (m == "#text") 28 | xml += v[m]; 29 | else if (m == "#cdata") 30 | xml += ""; 31 | else if (m.charAt(0) != "@") 32 | xml += toXml(v[m], m, ind+"\t"); 33 | } 34 | xml += (xml.charAt(xml.length-1)=="\n"?ind:"") + ""; 35 | } 36 | } 37 | else { 38 | xml += ind + "<" + name + ">" + v.toString() + ""; 39 | } 40 | return xml; 41 | }, xml=""; 42 | for (var m in o) 43 | xml += toXml(o[m], m, ""); 44 | return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, ""); 45 | } 46 | -------------------------------------------------------------------------------- /CognosScripts/xml2json.js: -------------------------------------------------------------------------------- 1 | /* This work is licensed under Creative Commons GNU LGPL License. 2 | 3 | License: http://creativecommons.org/licenses/LGPL/2.1/ 4 | Version: 0.9 5 | Author: Stefan Goessner/2006 6 | Web: http://goessner.net/ 7 | 8 | // 2016-05-13 doug pulse updated to handle xml input as string 9 | */ 10 | function xml2json(xml, tab) { 11 | var X = { 12 | toObj: function(xml) { 13 | var o = {}; 14 | if (xml.nodeType==1) { // element node .. 15 | if (xml.attributes.length) // element with attributes .. 16 | for (var i=0; i 1) 58 | o = X.escape(X.innerXml(xml)); 59 | else 60 | for (var n=xml.firstChild; n; n=n.nextSibling) 61 | o["#cdata"] = X.escape(n.nodeValue); 62 | } 63 | } 64 | if (!xml.attributes.length && !xml.firstChild) o = null; 65 | } 66 | else if (xml.nodeType==9) { // document.node 67 | o = X.toObj(xml.documentElement); 68 | } 69 | else 70 | alert("unhandled node type: " + xml.nodeType); 71 | return o; 72 | }, 73 | toJson: function(o, name, ind) { 74 | var json = name ? ("\""+name+"\"") : ""; 75 | if (o instanceof Array) { 76 | for (var i=0,n=o.length; i 1 ? ("\n"+ind+"\t"+o.join(",\n"+ind+"\t")+"\n"+ind) : o.join("")) + "]"; 79 | } 80 | else if (o == null) 81 | json += (name&&":") + "null"; 82 | else if (typeof(o) == "object") { 83 | var arr = []; 84 | for (var m in o) 85 | arr[arr.length] = X.toJson(o[m], m, ind+"\t"); 86 | json += (name?":{":"{") + (arr.length > 1 ? ("\n"+ind+"\t"+arr.join(",\n"+ind+"\t")+"\n"+ind) : arr.join("")) + "}"; 87 | } 88 | else if (typeof(o) == "string") 89 | json += (name&&":") + "\"" + o.toString() + "\""; 90 | else 91 | json += (name&&":") + o.toString(); 92 | return json; 93 | }, 94 | innerXml: function(node) { 95 | var s = "" 96 | if ("innerHTML" in node) 97 | s = node.innerHTML; 98 | else { 99 | var asXml = function(n) { 100 | var s = ""; 101 | if (n.nodeType == 1) { 102 | s += "<" + n.nodeName; 103 | for (var i=0; i"; 110 | } 111 | else 112 | s += "/>"; 113 | } 114 | else if (n.nodeType == 3) 115 | s += n.nodeValue; 116 | else if (n.nodeType == 4) 117 | s += ""; 118 | return s; 119 | }; 120 | for (var c=node.firstChild; c; c=c.nextSibling) 121 | s += asXml(c); 122 | } 123 | return s; 124 | }, 125 | escape: function(txt) { 126 | return txt.replace(/[\\]/g, "\\\\") 127 | .replace(/[\"]/g, '\\"') 128 | .replace(/[\n]/g, '\\n') 129 | .replace(/[\r]/g, '\\r'); 130 | }, 131 | removeWhite: function(e) { 132 | e.normalize(); 133 | for (var n = e.firstChild; n; ) { 134 | if (n.nodeType == 3) { // text node 135 | if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { // pure whitespace text node 136 | var nxt = n.nextSibling; 137 | e.removeChild(n); 138 | n = nxt; 139 | } 140 | else 141 | n = n.nextSibling; 142 | } 143 | else if (n.nodeType == 1) { // element node 144 | X.removeWhite(n); 145 | n = n.nextSibling; 146 | } 147 | else // any other node 148 | n = n.nextSibling; 149 | } 150 | return e; 151 | } 152 | }; 153 | 154 | if (typeof xml == "string") xml = parseXml(xml); 155 | 156 | if (xml.nodeType == 9) // document node 157 | xml = xml.documentElement; 158 | var json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t"); 159 | 160 | return "{\n" + (tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) + "\n}"; 161 | } 162 | 163 | function parseXml(xml) { 164 | // 2016-05-13 doug pulse updated to handle error in IE without an alert 165 | 166 | var dom = null; 167 | if (window.DOMParser) { 168 | try { 169 | dom = (new DOMParser()).parseFromString(xml, "text/xml"); 170 | } 171 | catch (e) { dom = null; } 172 | } 173 | else if (window.ActiveXObject) { 174 | try { 175 | dom = new ActiveXObject('Microsoft.XMLDOM'); 176 | dom.async = false; 177 | 178 | if (!dom.loadXML(xml)) { // parse error .. 179 | //window.alert(dom.parseError.reason + dom.parseError.srcText); 180 | xml = "" + dom.parseError.reason + dom.parseError.srcText + ""; 181 | dom.loadXML(xml); 182 | } 183 | } 184 | catch (e) { dom = null; } 185 | } 186 | else 187 | alert("cannot parse xml string!"); 188 | 189 | return dom; 190 | } 191 | -------------------------------------------------------------------------------- /ContentStore/ADSI.sql: -------------------------------------------------------------------------------- 1 | USE [master] 2 | GO 3 | EXEC master.dbo.sp_addlinkedserver @server = N'ADSI', @srvproduct=N'Active Directory Service Interfaces', @provider=N'ADSDSOObject', @datasrc=N'adsdatasource' 4 | EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'ADSI',@useself=N'False',@locallogin=NULL,@rmtuser=N'DOMAIN\USER',@rmtpassword='*********' 5 | GO 6 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'collation compatible', @optvalue=N'false' 7 | GO 8 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'data access', @optvalue=N'true' 9 | GO 10 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'dist', @optvalue=N'false' 11 | GO 12 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'pub', @optvalue=N'false' 13 | GO 14 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'rpc', @optvalue=N'false' 15 | GO 16 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'rpc out', @optvalue=N'false' 17 | GO 18 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'sub', @optvalue=N'false' 19 | GO 20 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'connect timeout', @optvalue=N'0' 21 | GO 22 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'collation name', @optvalue=null 23 | GO 24 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'lazy schema validation', @optvalue=N'false' 25 | GO 26 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'query timeout', @optvalue=N'0' 27 | GO 28 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'use remote collation', @optvalue=N'true' 29 | GO 30 | EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'remote proc transaction promotion', @optvalue=N'true' 31 | GO -------------------------------------------------------------------------------- /ContentStore/BrokenShortcuts.sql: -------------------------------------------------------------------------------- 1 | ; 2 | with cte( 3 | PCMID, 4 | CMID, 5 | ReportName, 6 | ReportPath, 7 | done, 8 | RootNode 9 | ) as 10 | ( 11 | select o.PCMID 12 | , o.CMID 13 | , n.NAME 14 | , cast(n.NAME as varchar(max)) 15 | , 0 16 | , cast(n.NAME as varchar(max)) 17 | 18 | from CMOBJECTS o 19 | inner join CMOBJNAMES n on n.CMID = o.CMID 20 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 21 | inner join CMREFNOORD1 r on r.CMID = o.CMID 22 | inner join CMOBJECTS b on b.CMID = r.REFCMID 23 | inner join CMOBJECTS do on do.CMID = b.PCMID 24 | inner join CMOBJNAMES dn on dn.CMID = do.CMID 25 | 26 | where n.ISDEFAULT = 1 27 | and c.NAME in ('reportView', 'shortcut') 28 | and dn.NAME = 'Deleted Object Folder' 29 | 30 | union all 31 | select o.PCMID 32 | , o.CMID 33 | , cte.ReportName 34 | , cast(n.NAME + '/' + cte.ReportPath as varchar(max)) 35 | , case when left(n.NAME, 8) = 'MyNamespace:' then 1 else 0 end 36 | , cast(n.NAME as varchar(max)) 37 | 38 | from CMOBJECTS o 39 | inner join CMOBJNAMES n on n.CMID = o.CMID 40 | inner join cte cte on cte.PCMID = o.CMID 41 | 42 | where n.ISDEFAULT = 1 43 | and n.CMID != 0 44 | and cte.done = 0 45 | ) 46 | 47 | 48 | select replace(c.ReportPath, c.RootNode, isnull(u.Name, c.RootNode)) as ReportPath 49 | 50 | from cte c 51 | left outer join ( 52 | select a.OBJID 53 | , b.NAME 54 | 55 | from CMOBJPROPS1 a 56 | inner join CMOBJPROPS33 b on b.CMID = a.CMID 57 | ) u on u.OBJID = c.RootNode 58 | 59 | where (c.ReportPath like 'Team Content%' 60 | or c.ReportPath like 'MyNamespace:%') 61 | 62 | order by ReportPath 63 | -------------------------------------------------------------------------------- /ContentStore/Capabilities.ps1: -------------------------------------------------------------------------------- 1 | $CognosEnvironment = Read-Host "Cognos Environment (P, Q, D):" 2 | switch($CognosEnvironment) { 3 | "P" { 4 | $dbServer = "ProdDBServer" 5 | $dbName = "ProdDBName" 6 | } 7 | "Q" { 8 | $dbServer = "QADBServer" 9 | $dbName = "QADBName" 10 | } 11 | "D" { 12 | $dbServer = "DevDBServer" 13 | $dbName = "DevDBName" 14 | } 15 | } 16 | 17 | $AuthenticationNamespace = "NamespaceName" 18 | $DomainName = "DomainName" 19 | 20 | " 21 | 22 | 23 | 24 | Getting data from the database. 25 | This may take a couple minutes. 26 | 27 | 28 | 29 | " 30 | 31 | $sqlquery = " 32 | declare @DirectoryNamespace varchar(128) = '$DirectoryNamespace' 33 | declare @DomainName varchar(255) = '$DomainName' 34 | ; 35 | with 36 | capabilities as ( 37 | select cast(n.NAME as varchar(max)) as CapabilityPath 38 | , n.NAME 39 | , c.NAME as class 40 | , o.CMID 41 | , o.PCMID 42 | , o.DISABLED 43 | 44 | from CMOBJECTS o 45 | inner join CMOBJNAMES n on n.CMID = o.CMID 46 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 47 | 48 | where n.ISDEFAULT = 1 49 | and c.NAME = 'capability' 50 | and n.NAME = 'Capability' 51 | 52 | union all 53 | select cast(cap.CapabilityPath + '/' + n.NAME as varchar(max)) 54 | , n.NAME 55 | , c.NAME 56 | , o.CMID 57 | , o.PCMID 58 | , o.DISABLED 59 | from capabilities cap 60 | inner join CMOBJECTS o on o.PCMID = cap.CMID 61 | inner join CMOBJNAMES n on n.CMID = o.CMID 62 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 63 | 64 | where n.ISDEFAULT = 1 65 | ) 66 | 67 | select * 68 | into #capabilities 69 | from capabilities 70 | ; 71 | with 72 | capabilitypolicy as ( 73 | select c.CapabilityPath 74 | , c.DISABLED 75 | , CONVERT(varchar(max), CONVERT(varbinary(max), p.POLICIES, 1), 2) as pol 76 | from #capabilities c 77 | inner join CMPOLICIES p on p.CMID = c.CMID 78 | ), 79 | cte ( 80 | CapabilityPath, 81 | pol, 82 | l, 83 | pos, 84 | curr, 85 | valout 86 | ) as ( 87 | -- Loop through the value 2 characters (1 hex value) at a time. 88 | -- Convert each value to ASCII. 89 | -- We'll replace anything small (non-printing characters) with LF to keep it simple. 90 | -- That may not be the best solution. 91 | select CapabilityPath 92 | , pol 93 | , len(pol) as l 94 | , 3 as pos 95 | , substring(pol, 1, 2) as curr 96 | , case 97 | when convert(int, convert(varbinary, '0x' + substring(pol, 1, 2), 1)) < 32 then char(10) 98 | else cast(cast(convert(binary(2), '0x' + substring(pol, 1, 2), 1) as char(1)) as varchar(max)) 99 | end as valout 100 | from capabilitypolicy 101 | union all 102 | select CapabilityPath 103 | , pol 104 | , l 105 | , pos + 2 as pos 106 | , substring(pol, pos, 2) as curr 107 | , valout + 108 | case 109 | when convert(int, convert(varbinary, '0x' + substring(pol, pos, 2), 1)) < 32 then char(10) 110 | else cast(cast(convert(binary(2), '0x' + substring(pol, pos, 2), 1) as char(1)) as varchar(max)) 111 | end as valout 112 | from cte 113 | where pos < l 114 | ), 115 | cte2 as ( 116 | -- Rank to identify the final value. 117 | select * 118 | , rank() over (partition by CapabilityPath order by pos desc) as rnk 119 | from cte 120 | ), 121 | a as ( 122 | -- We need only the results of the last step. 123 | select CapabilityPath 124 | , valout 125 | from cte2 126 | where rnk = 1 127 | ), 128 | q as ( 129 | --select CapabilityPath 130 | --, ROW_NUMBER() over (partition by CapabilityPath order by CapabilityPath) as rownum -- not reliable because string_split doesn't guarantee order until SQL 2022 131 | ----, ROW_NUMBER() over (partition by CapabilityPath order by ordinal) as rownum -- Use with SQL 2022 or later 132 | --, value as val 133 | ----, substring(value, 11, 32) as val 134 | --from a 135 | -- cross apply string_split(valout, char(10)) -- not reliable because string_split doesn't guarantee order until SQL 2022 136 | -- --cross apply string_split(valout, char(10), 1) -- Use with SQL 2022 or later 137 | 138 | -- SQL Server 2012 does not have string_split() 139 | SELECT CapabilityPath 140 | , ROW_NUMBER() over (partition by CapabilityPath order by CapabilityPath) as rownum 141 | , Split.a.value('.', 'NVARCHAR(MAX)') val 142 | FROM ( 143 | SELECT CapabilityPath 144 | , CAST('' + 145 | REPLACE( 146 | replace( 147 | replace( 148 | replace( 149 | replace( 150 | replace( 151 | valout, '`"', char(10) 152 | ), '<', char(10) 153 | ), '>', char(10) 154 | ), '&', char(10) 155 | ), '''', char(10) 156 | ), char(10), '' 157 | ) + '' AS XML 158 | ) AS String 159 | from a 160 | ) AS A 161 | CROSS APPLY String.nodes('/X') AS Split(a) 162 | ) 163 | 164 | -- Using a temporary table here reduces run time from 88 seconds to 8 seconds. 165 | select * 166 | into #q 167 | from q 168 | OPTION (MAXRECURSION 0) 169 | 170 | ; 171 | 172 | with 173 | perms as ( 174 | select perm 175 | from ( 176 | values 177 | ('execute') 178 | , ('read') 179 | , ('setPolicy') 180 | , ('traverse') 181 | , ('write') 182 | ) v (perm) 183 | ), 184 | capabilityPerms as ( 185 | -- Cognos roles 186 | select q.CapabilityPath 187 | , q.rownum 188 | , n.NAME 189 | from #q q 190 | inner join CMOBJNAMES n on n.CMID = cast(SUBSTRING(q.val, 3, CHARINDEX(':', q.val, 3) - 3) as int) 191 | inner join CMOBJECTS o on o.CMID = n.CMID 192 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 193 | where q.val like '::%' 194 | and CHARINDEX(':', val, 3) > 0 195 | and n.ISDEFAULT = 1 196 | and c.NAME = 'role' 197 | 198 | -- Cognos groups? Cognos groups and users? 199 | union 200 | select q.CapabilityPath 201 | , q.rownum 202 | , SUBSTRING(val, 3, 400) as 'Name' 203 | from #q q 204 | where q.val like '::%' 205 | and CHARINDEX(':', val, 3) = 0 206 | 207 | -- AD groups and users? 208 | union 209 | select q.CapabilityPath 210 | , q.rownum 211 | , @DomainName + '\' + u.NAME 212 | from #q q 213 | inner join CMOBJNAMES n on n.NAME = q.val 214 | inner join cmobjprops33 u on u.CMID = n.CMID 215 | where n.NAME like @DirectoryNamespace + '%' 216 | 217 | -- permissions (setPolicy, execute, etc.) 218 | union 219 | select q.CapabilityPath 220 | , q.rownum 221 | , p.perm 222 | from #q q 223 | inner join perms p on q.val like '%' + p.perm + '%' 224 | ), 225 | executeStart as ( 226 | select cp.CapabilityPath 227 | , cp.rownum 228 | , cp.NAME 229 | from capabilityPerms cp 230 | where cp.NAME = 'execute' 231 | ), 232 | readStart as ( 233 | select cp.CapabilityPath 234 | , cp.rownum 235 | , cp.NAME 236 | from capabilityPerms cp 237 | where cp.NAME = 'read' 238 | ), 239 | setPolicyStart as ( 240 | select cp.CapabilityPath 241 | , cp.rownum 242 | , cp.NAME 243 | from capabilityPerms cp 244 | where cp.NAME = 'setPolicy' 245 | ), 246 | traverseStart as ( 247 | select cp.CapabilityPath 248 | , cp.rownum 249 | , cp.NAME 250 | from capabilityPerms cp 251 | where cp.NAME = 'traverse' 252 | ), 253 | writeStart as ( 254 | select cp.CapabilityPath 255 | , cp.rownum 256 | , cp.NAME 257 | from capabilityPerms cp 258 | where cp.NAME = 'write' 259 | ), 260 | permClass as ( 261 | select cp.CapabilityPath 262 | , cp.rownum 263 | , cp.NAME 264 | , es.rownum as executeStart 265 | , rs.rownum as readStart 266 | , ss.rownum as setPolicyStart 267 | , ts.rownum as traverseStart 268 | , ws.rownum as writeStart 269 | from capabilityPerms cp 270 | left outer join executeStart es on es.CapabilityPath = cp.CapabilityPath 271 | left outer join readStart rs on rs.CapabilityPath = cp.CapabilityPath 272 | left outer join setPolicyStart ss on ss.CapabilityPath = cp.CapabilityPath 273 | left outer join traverseStart ts on ts.CapabilityPath = cp.CapabilityPath 274 | left outer join writeStart ws on ws.CapabilityPath = cp.CapabilityPath 275 | ) 276 | 277 | select c.CapabilityPath 278 | , case 279 | when pc.rownum between coalesce(pc.executeStart, 999) and coalesce(pc.readStart, pc.setPolicyStart, pc.traverseStart, pc.writeStart, 999) 280 | then 'execute' 281 | when pc.rownum between coalesce(pc.readStart, 999) and coalesce(pc.setPolicyStart, pc.traverseStart, pc.writeStart, 999) 282 | then 'read' 283 | when pc.rownum between coalesce(pc.setPolicyStart, 999) and coalesce(pc.traverseStart, pc.writeStart, 999) 284 | then 'setPolicy' 285 | when pc.rownum between coalesce(pc.traverseStart, 999) and coalesce(pc.writeStart, 999) 286 | then 'traverse' 287 | when pc.rownum between coalesce(pc.writeStart, 999) and 999 288 | then 'write' 289 | else 'inherited' 290 | end as permission 291 | , pc.NAME as PrincipalName 292 | from #capabilities c 293 | left outer join permClass pc on pc.CapabilityPath = c.CapabilityPath 294 | and pc.NAME not in ( 295 | select perm 296 | from perms 297 | ) 298 | --and pc.NAME = 'BI Administrators' 299 | order by 1, 2, 3 300 | 301 | drop table #q 302 | drop table #capabilities 303 | " 304 | 305 | $result = Invoke-Sqlcmd $sqlquery ` 306 | -ServerInstance $dbServer ` 307 | -Database $dbName ` 308 | -MaxCharLength 1000000 ` 309 | -ConnectionTimeout 10 ` 310 | -QueryTimeout 600 ` 311 | -TrustServerCertificate 312 | 313 | $l = $result.length 314 | $Capability = @() 315 | $i = 0 316 | $startTime = Get-Date 317 | 318 | foreach($row in $result) { 319 | $r = [PSCustomObject]@{} 320 | $r | Add-Member -MemberType NoteProperty -Name 'CapabilityPath' -Value $row.CapabilityPath 321 | $r | Add-Member -MemberType NoteProperty -Name 'permission' -Value $row.permission 322 | $r | Add-Member -MemberType NoteProperty -Name 'PrincipalName' -Value $row.PrincipalName 323 | 324 | $Capability += $r 325 | 326 | $i++ 327 | $p = [int]($i * 100 / $l) 328 | 329 | $elapsed = ((Get-Date) - $startTime).TotalSeconds 330 | $remainingItems = $l - $i 331 | $averageItemTime = $elapsed / $i 332 | 333 | Write-Progress "Processing $l capabilities" ` 334 | -Status "$i capabilities processed" ` 335 | -PercentComplete $p ` 336 | -SecondsRemaining ($remainingItems * $averageItemTime) 337 | } 338 | 339 | 340 | $f = Join-Path (Join-Path $env:USERPROFILE "Downloads") "Capabilities$CognosEnvironment.csv" 341 | 342 | $Capability | Export-Csv -Path $f -NoTypeInformation 343 | Start-Process -FilePath $f 344 | -------------------------------------------------------------------------------- /ContentStore/CognosScheduleEmailRecients.sql: -------------------------------------------------------------------------------- 1 | 2 | create table #report ( 3 | ReportId int, 4 | ReportName varchar(256), 5 | ReportPath varchar(4000) 6 | ) 7 | 8 | create table #schedules ( 9 | ScheduleId int, 10 | ObjectName varchar(256), 11 | ObjectPath varchar(4000), 12 | ReportId int 13 | ) 14 | 15 | create table #ScheduleDelivery ( 16 | CMID int, 17 | DELIVOPTIONS ntext, 18 | CAMID xml, 19 | Email xml 20 | ) 21 | 22 | create table #CAMID ( 23 | id int identity(1,1), 24 | CMID int, 25 | ReportName varchar(100), 26 | ReportPath varchar(500), 27 | SchedulePath varchar(500), 28 | CAMID xml 29 | ) 30 | 31 | create table #Email ( 32 | id int identity(1,1), 33 | CMID int, 34 | ReportName varchar(100), 35 | ReportPath varchar(500), 36 | SchedulePath varchar(500), 37 | Email xml 38 | ) 39 | 40 | create table #output ( 41 | id int identity(1,1), 42 | CMID int, 43 | ReportName varchar(100), 44 | ReportPath varchar(500), 45 | SchedulePath varchar(500), 46 | email varchar(100) 47 | ) 48 | 49 | --================================================================================ 50 | -- get locations of reports and report views 51 | ; 52 | with cte(PCMID, 53 | CMID, 54 | ReportId, 55 | ReportName, 56 | ReportPath, 57 | done, 58 | RootNode) as 59 | 60 | ( 61 | select o.PCMID 62 | , n.CMID 63 | , n.CMID 64 | , n.NAME 65 | , cast(n.NAME as varchar(max)) 66 | , 0 67 | , cast(n.NAME as varchar(max)) 68 | from CMOBJECTS o 69 | inner join CMOBJNAMES n on n.CMID = o.CMID 70 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 71 | where n.ISDEFAULT = 1 72 | and isdate(n.NAME) = 0 73 | and c.name in ('report')--, 'reportview') 74 | 75 | union all 76 | select o.PCMID 77 | , n.CMID 78 | , cte.ReportId 79 | , cte.ReportName 80 | , cast(n.NAME + '/' + cte.ReportPath as varchar(max)) 81 | , case when left(n.NAME, 8) = 'AuthenticationNamespaceName:' then 1 else 0 end 82 | , cast(n.NAME as varchar(max)) 83 | from CMOBJECTS o 84 | inner join CMOBJNAMES n on n.CMID = o.CMID 85 | inner join cte cte on cte.PCMID = n.CMID 86 | where n.ISDEFAULT = 1 87 | and n.CMID != 0 88 | and cte.done = 0 89 | ) 90 | 91 | insert #report 92 | select c.ReportId 93 | , c.ReportName 94 | , replace(c.ReportPath, c.RootNode, isnull(u.Name, c.RootNode)) as ReportPath 95 | from cte c 96 | left outer join ( 97 | select a.OBJID 98 | , b.NAME 99 | 100 | from CMOBJPROPS1 a 101 | inner join CMOBJPROPS33 b on b.CMID = a.CMID 102 | ) u on u.OBJID = c.RootNode 103 | where (c.ReportPath like 'Team Content%' 104 | or c.ReportPath like 'AuthenticationNamespaceName:%') -- "My Content" 105 | order by ReportPath 106 | 107 | 108 | 109 | --================================================================================ 110 | -- get locations of schedules 111 | ; 112 | with cte(PCMID, 113 | CMID, 114 | ScheduleId, 115 | ObjectName, 116 | ObjectPath, 117 | done, 118 | RootNode, 119 | ReportId) as 120 | 121 | ( 122 | select o.PCMID 123 | , n.CMID 124 | , n.CMID 125 | , n.NAME 126 | , cast(n.NAME as varchar(max)) 127 | , 0 128 | , cast(n.NAME as varchar(max)) 129 | , 0 130 | from CMOBJECTS o 131 | inner join CMOBJNAMES n on n.CMID = o.CMID 132 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 133 | where n.ISDEFAULT = 1 134 | and c.name = 'schedule' 135 | 136 | union all 137 | select o.PCMID 138 | , n.CMID 139 | , cte.ScheduleId 140 | , cte.ObjectName 141 | , cast(n.NAME + '/' + cte.ObjectPath as varchar(max)) 142 | , case when left(n.NAME, 8) = 'AuthenticationNamespaceName:' then 1 else 0 end 143 | , cast(n.NAME as varchar(max)) 144 | , case 145 | when c.NAME in ('report', 'reportview') then o.CMID 146 | else cte.ReportId 147 | end 148 | from CMOBJECTS o 149 | inner join CMOBJNAMES n on n.CMID = o.CMID 150 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 151 | inner join cte cte on cte.PCMID = n.CMID 152 | where n.ISDEFAULT = 1 153 | and n.CMID != 0 154 | and cte.done = 0 155 | ) 156 | 157 | insert #schedules 158 | select c.ScheduleId 159 | , c.ObjectName 160 | , replace(c.ObjectPath, c.RootNode, isnull(u.Name, c.RootNode)) as ObjectPath 161 | , c.ReportId 162 | from cte c 163 | left outer join ( 164 | select a.OBJID 165 | , b.NAME 166 | 167 | from CMOBJPROPS1 a 168 | inner join CMOBJPROPS33 b on b.CMID = a.CMID 169 | ) u on u.OBJID = c.RootNode 170 | where c.ObjectPath like 'Team Content%' 171 | or c.ObjectPath like 'AuthenticationNamespaceName:%' 172 | order by ObjectPath 173 | 174 | 175 | 176 | --================================================================================ 177 | -- get delivery info as xml 178 | insert #ScheduleDelivery 179 | select CMID 180 | , DELIVOPTIONS 181 | , cast(case 182 | when cast(DELIVOPTIONS as varchar(max)) like '%to;%' 183 | then replace(replace(SUBSTRING(cast(DELIVOPTIONS as varchar(max)), CHARINDEX('', cast(DELIVOPTIONS as varchar(max)), CHARINDEX('', cast(DELIVOPTIONS as varchar(max)), CHARINDEX('true%' 196 | 197 | 198 | 199 | --================================================================================ 200 | 201 | insert #CAMID 202 | select sd.CMID 203 | , r.ReportName 204 | , r.ReportPath 205 | , s.ObjectPath 206 | , sd.CAMID 207 | from #ScheduleDelivery sd 208 | inner join #schedules s on s.ScheduleId = sd.CMID 209 | inner join #report r on r.ReportId = s.ReportId 210 | where cast(sd.CAMID as varchar(max)) <> '' 211 | 212 | insert #Email 213 | select sd.CMID 214 | , r.ReportName 215 | , r.ReportPath 216 | , s.ObjectPath 217 | , sd.Email 218 | from #ScheduleDelivery sd 219 | inner join #schedules s on s.ScheduleId = sd.CMID 220 | inner join #report r on r.ReportId = s.ReportId 221 | where cast(sd.Email as varchar(max)) <> '' 222 | 223 | 224 | declare @maxId int 225 | select @maxId = max(id) 226 | from #CAMID 227 | 228 | declare @i int 229 | set @i = 1 230 | 231 | declare @CMID int 232 | declare @ReportName varchar(100) 233 | declare @ReportPath varchar(500) 234 | declare @SchedulePath varchar(500) 235 | declare @arrlen int 236 | 237 | declare @x xml 238 | declare @xOut varchar(128) 239 | 240 | 241 | while @i <= @maxId 242 | begin 243 | select @CMID = CMID 244 | , @ReportName = ReportName 245 | , @ReportPath = ReportPath 246 | , @SchedulePath = SchedulePath 247 | , @x = CAMID 248 | from #CAMID n 249 | where id = @i 250 | 251 | insert #output 252 | select x.cmid 253 | , rn 254 | , rp 255 | , sp 256 | , b.NAME 257 | from ( 258 | select @CMID as cmid 259 | , @ReportName as rn 260 | , @ReportPath as rp 261 | , @SchedulePath as sp 262 | , replace(replace(pd.value('text()[1]', 'varchar(128)'), 'CAMID("', ''), '")', '') as camid 263 | from @x.nodes('//value') as x(Rec) 264 | cross apply @x.nodes('//value/item') as i(pd) 265 | ) x 266 | inner join CMOBJPROPS1 a on a.OBJID = x.camid 267 | inner join CMOBJPROPS33 b on b.CMID = a.CMID 268 | 269 | set @i = @i + 1 270 | end 271 | 272 | 273 | 274 | select @maxId = max(id) 275 | from #Email 276 | 277 | set @i = 1 278 | 279 | while @i <= @maxId 280 | begin 281 | select @CMID = CMID 282 | , @ReportName = ReportName 283 | , @ReportPath = ReportPath 284 | , @SchedulePath = SchedulePath 285 | , @x = Email 286 | from #Email n 287 | where id = @i 288 | 289 | insert #output 290 | select @CMID 291 | , @ReportName 292 | , @ReportPath 293 | , @SchedulePath 294 | , pd.value('text()[1]', 'varchar(128)') 295 | from @x.nodes('//value') as x(Rec) 296 | cross apply @x.nodes('//value/item') as i(pd) 297 | 298 | set @i = @i + 1 299 | end 300 | 301 | 302 | select * 303 | from #output 304 | 305 | 306 | drop table #report 307 | drop table #schedules 308 | drop table #ScheduleDelivery 309 | drop table #CAMID 310 | drop table #Email 311 | drop table #output 312 | -------------------------------------------------------------------------------- /ContentStore/LocateSchedules.sql: -------------------------------------------------------------------------------- 1 | -- get locations of schedules 2 | ; 3 | with cte(PCMID, 4 | CMID, 5 | ScheduleId, 6 | ObjectName, 7 | ObjectPath, 8 | done, 9 | RootNode, 10 | Modified, 11 | ReportId) as 12 | ( 13 | select o.PCMID 14 | , n.CMID 15 | , n.CMID 16 | , n.NAME 17 | , cast(n.NAME as varchar(max)) 18 | , 0 19 | , cast(n.NAME as varchar(max)) 20 | , o.MODIFIED 21 | , 0 22 | from CMOBJECTS o 23 | inner join CMOBJNAMES n on n.CMID = o.CMID 24 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 25 | where n.ISDEFAULT = 1 26 | and c.name = 'schedule' 27 | 28 | union all 29 | select o.PCMID 30 | , n.CMID 31 | , cte.ScheduleId 32 | , cte.ObjectName 33 | , cast(n.NAME + '/' + cte.ObjectPath as varchar(max)) 34 | , case when left(n.NAME, 8) = 'MyNamespace:' then 1 else 0 end 35 | , cast(n.NAME as varchar(max)) 36 | , cte.Modified 37 | , case 38 | when c.NAME in ('report', 'reportview', 'dataset2') then o.CMID 39 | else cte.ReportId 40 | end 41 | from CMOBJECTS o 42 | inner join CMOBJNAMES n on n.CMID = o.CMID 43 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 44 | inner join cte cte on cte.PCMID = n.CMID 45 | where n.ISDEFAULT = 1 46 | and n.CMID != 0 47 | and cte.done = 0 48 | ) 49 | 50 | select c.ScheduleId 51 | , c.ObjectName 52 | , c.Modified 53 | , c.ObjectPath 54 | , c.ReportId 55 | , c.RootNode 56 | into #schedules 57 | from cte c 58 | where c.ObjectPath like 'Team Content%' 59 | or c.ObjectPath like 'MyNamespace:%' 60 | order by ObjectPath 61 | 62 | select s.ReportId 63 | , replace(reverse(substring(reverse(s.ObjectPath), charindex('/', reverse(s.ObjectPath)) + 1, 4000)), s.RootNode, isnull(u.Name, s.RootNode)) as ObjectPath 64 | , case 65 | when schedtype.interval = 'trigger' then 'on trigger ' + t.SCHEDTRIGNAME 66 | else 'Every ' + 67 | cast(c.EVERYNPERIODS as varchar(5)) + ' ' + 68 | schedtype.interval + 69 | case 70 | when c.EVERYNPERIODS > 1 then 's' 71 | else '' 72 | end + 73 | case 74 | when schedtype.interval = 'hour' then ' between ' + 75 | format( 76 | CONVERT( 77 | datetime, 78 | SWITCHOFFSET( 79 | CONVERT( 80 | datetimeoffset, 81 | c.INTRARECURSTART 82 | ), 83 | DATENAME( 84 | TzOffset, 85 | SYSDATETIMEOFFSET() 86 | ) 87 | ) 88 | ), 89 | 'HH:mm:ss' 90 | ) + 91 | ' and ' + 92 | format( 93 | CONVERT( 94 | datetime, 95 | SWITCHOFFSET( 96 | CONVERT( 97 | datetimeoffset, 98 | c.INTRARECUREND 99 | ), 100 | DATENAME( 101 | TzOffset, 102 | SYSDATETIMEOFFSET() 103 | ) 104 | ) 105 | ), 106 | 'HH:mm:ss' 107 | ) + ' ' 108 | when schedtype.interval = 'day' then ' ' 109 | when schedtype.interval = 'year' then ' on day ' + cast(c.YEARLYABSDAY as varchar(5)) + ' of ' + DATENAME(month, DATEFROMPARTS(2020, c.YEARLYABSMONTH + 1, 1)) /*'month ' + cast(c.YEARLYABSMONTH as varchar(5))*/ + ' ' 110 | else ' on ' + 111 | case 112 | when schedtype.interval = 'week' then 113 | case 114 | when c.WEEKLYMONDAY = 1 then 'monday ' 115 | else '' 116 | end + 117 | case 118 | when c.WEEKLYTUESDAY = 1 then 'tuesday ' 119 | else '' 120 | end + 121 | case 122 | when c.WEEKLYWEDNESDAY = 1 then 'wednesday ' 123 | else '' 124 | end + 125 | case 126 | when c.WEEKLYTHURSDAY = 1 then 'thursday ' 127 | else '' 128 | end + 129 | case 130 | when c.WEEKLYFRIDAY = 1 then 'friday ' 131 | else '' 132 | end + 133 | case 134 | when c.WEEKLYSATURDAY = 1 then 'saturday ' 135 | else '' 136 | end + 137 | case 138 | when c.WEEKLYSUNDAY = 1 then 'sunday ' 139 | else '' 140 | end 141 | when schedtype.interval = 'month' then 142 | case 143 | when schedtype.typename = 'monthly by day of month' then 'day ' + cast(c.MONTHLYABSDAY as varchar(5)) + ' ' 144 | when schedtype.typename = 'monthly by day of week' then daynames.name /*cast(c.MONTHLYRELDAY as varchar(5))*/ + ' of week ' + cast(c.MONTHLYRELWEEK + 1 as varchar(5)) + ' ' -- this isn't right 145 | else '' 146 | end 147 | else '' 148 | end 149 | end + 150 | 'at ' + 151 | format( 152 | CONVERT( 153 | datetime, 154 | SWITCHOFFSET( 155 | CONVERT( 156 | datetimeoffset, 157 | c.STARTDATE 158 | ), 159 | DATENAME( 160 | TzOffset, 161 | SYSDATETIMEOFFSET() 162 | ) 163 | ) 164 | ), 165 | case 166 | when schedtype.interval = 'hour' then 'mm' 167 | else 'HH:mm:ss' 168 | end 169 | ) 170 | end as ScheduleDescription 171 | , format( 172 | CONVERT( 173 | datetime, 174 | SWITCHOFFSET( 175 | CONVERT( 176 | datetimeoffset, 177 | c.STARTDATE 178 | ), 179 | DATENAME( 180 | TzOffset, 181 | SYSDATETIMEOFFSET() 182 | ) 183 | ) 184 | ), 185 | 'HH:mm:ss' 186 | ) as StartTime 187 | into #reports 188 | from #schedules s 189 | inner join CMOBJPROPS2 c on c.CMID = s.ScheduleId 190 | left outer join CMOBJPROPS51 t on t.CMID = s.ScheduleId 191 | left outer join (values (2, 'monthly by day of week', 'month') 192 | , (1, 'monthly by day of month', 'month') 193 | , (4, 'weekly', 'week') 194 | , (0, 'daily', 'day') 195 | , (9, 'hourly', 'hour') 196 | , (7, 'triggered', 'trigger') 197 | , (5, 'yearly', 'year') 198 | ) schedtype (type, typename, interval) on schedtype.type = c.TYPE 199 | left outer join ( 200 | select a.OBJID 201 | , b.NAME 202 | 203 | from CMOBJPROPS1 a 204 | inner join CMOBJPROPS33 b on b.CMID = a.CMID 205 | ) u on u.OBJID = s.RootNode 206 | left outer join (values (0, 'Sunday') 207 | , (1, 'Monday') 208 | , (2, 'Tuesday') 209 | , (3, 'Wednesday') 210 | , (4, 'Thursday') 211 | , (5, 'Friday') 212 | , (6, 'Saturday') 213 | ) daynames (num, name) on daynames.num = c.MONTHLYRELDAY 214 | 215 | order by format( 216 | CONVERT( 217 | datetime, 218 | SWITCHOFFSET( 219 | CONVERT( 220 | datetimeoffset, 221 | c.STARTDATE 222 | ), 223 | DATENAME( 224 | TzOffset, 225 | SYSDATETIMEOFFSET() 226 | ) 227 | ) 228 | ), 229 | 'HH:mm:ss' 230 | ) 231 | , c.type 232 | , s.ObjectPath 233 | 234 | 235 | 236 | select pn.NAME as Package 237 | , r.ObjectPath as ReportPath 238 | , r.ScheduleDescription 239 | , r.StartTime 240 | --, r.ReportId 241 | 242 | from #reports r 243 | inner join CMREFNOORD1 ref on ref.CMID = r.ReportId 244 | inner join CMOBJECTS po on po.CMID = ref.REFCMID 245 | inner join CMOBJNAMES pn on pn.CMID = po.CMID 246 | inner join CMCLASSES pc on pc.CLASSID = po.CLASSID 247 | 248 | where pn.ISDEFAULT = 1 249 | and pc.NAME = 'package' 250 | 251 | order by Package 252 | , StartTime 253 | 254 | 255 | 256 | drop table #schedules 257 | drop table #reports 258 | -------------------------------------------------------------------------------- /ContentStore/ModuleAndModelSpecs.sql: -------------------------------------------------------------------------------- 1 | use IBMCognos 2 | GO 3 | ; 4 | 5 | declare @DirectoryNamespace varchar(255) = 'MyNamespace' 6 | declare @DirectoryNamespaceLength int = 11 7 | 8 | -- data container full path 9 | -- ...for all packages, modules, uploaded files, and datasets 10 | ; 11 | with 12 | objname as ( 13 | select o.CMID 14 | , coalesce(n2.name, n.NAME) as 'NAME' 15 | from CMOBJECTS o 16 | left outer join CMOBJNAMES n on n.CMID = o.CMID 17 | and n.LOCALEID = 92 18 | left outer join CMOBJNAMES n2 on n2.CMID = o.CMID 19 | and n2.LOCALEID = 118 20 | ), 21 | package ( 22 | PCMID 23 | , CMID 24 | , ObjectId 25 | , ObjectName 26 | , ObjectPath 27 | , done 28 | , RootNode 29 | , ObjectType 30 | , ParentObjectType 31 | ) as ( 32 | select o.PCMID 33 | , n.CMID 34 | , n.CMID 35 | , cast(n.NAME as varchar(550)) 36 | , cast(n.NAME as varchar(max)) 37 | , 0 38 | , cast(n.NAME as varchar(max)) 39 | , c.NAME 40 | , cast(null as varchar(50)) 41 | from CMOBJECTS o 42 | inner join objname n on n.CMID = o.CMID 43 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 44 | --where c.name in ('package', 'module', 'uploadedFile', 'dataSet2') 45 | --where c.name in ('module', 'model') 46 | -- and n.NAME in ('! BigBudgetModule', 'May New data module') 47 | --where c.name = 'model' 48 | 49 | union all 50 | select o.PCMID 51 | , n.CMID 52 | , p.ObjectId 53 | , cast( 54 | case 55 | when p.ParentObjectType is null 56 | then 57 | case 58 | when c.NAME = 'folder' 59 | then p.ObjectName 60 | when c.NAME = 'package' 61 | then n.NAME 62 | when c.NAME = 'exploration' 63 | then n.NAME + '--' + p.ObjectName 64 | end 65 | else p.ObjectName 66 | end as varchar(550)) 67 | , case 68 | when p.ParentObjectType is null and c.NAME = 'package' 69 | then cast(n.NAME as varchar(max)) 70 | else cast(n.NAME + '/' + p.ObjectPath as varchar(max)) 71 | end 72 | , case when left(n.NAME, @DirectoryNamespaceLength + 1) = @DirectoryNamespace + ':' then 1 else 0 end 73 | , cast(n.NAME as varchar(max)) 74 | , p.ObjectType 75 | , case when p.ParentObjectType is null then c.NAME else p.ParentObjectType end 76 | from CMOBJECTS o 77 | inner join objname n on n.CMID = o.CMID 78 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 79 | inner join package p on p.PCMID = n.CMID 80 | where n.CMID != 0 81 | and p.done = 0 82 | ), 83 | content as ( 84 | -- There will be many paths for the same object. 85 | -- Keep only the path for each that starts at the root. 86 | select p.ObjectId 87 | , p.ObjectName 88 | , p.ObjectType 89 | , replace(replace(p.ObjectPath, p.RootNode, isnull(u.Name, p.RootNode)), '/(en) ', '/') as ObjectPath 90 | , p.ParentObjectType 91 | 92 | from package p 93 | left outer join ( 94 | select a.OBJID 95 | , b.NAME 96 | 97 | from CMOBJPROPS1 a 98 | inner join CMOBJPROPS33 b on b.CMID = a.CMID 99 | ) u on u.OBJID = p.RootNode 100 | where (p.ObjectPath like 'Team Content%' 101 | or p.ObjectPath like @DirectoryNamespace + ':%') 102 | ), 103 | objprops86 as ( 104 | select s.CMID 105 | , cast(s.CBASEDEF as varchar(max)) as CBASEDEF 106 | from CMOBJPROPS86 s 107 | ), 108 | zip as ( 109 | select 110 | d.ObjectId 111 | , d.ObjectName 112 | , d.ObjectType 113 | , d.ParentObjectType 114 | , d.ObjectPath 115 | --, module.CBASEDEF AS CBASEDEF_BASE64 116 | , case d.ObjectType 117 | when 'module' then CAST('' AS XML).value('xs:base64Binary(sql:column("module.CBASEDEF"))', 'VARBINARY(MAX)') 118 | when 'model' then cast(model.cmodel as varbinary(max)) 119 | end as CBASEDEF_COMPRESSED 120 | from content d 121 | left outer join objprops86 module on module.CMID = d.ObjectId 122 | left outer join CMOBJPROPS7 model on model.CMID = d.ObjectId 123 | ) 124 | 125 | select 126 | ObjectId 127 | , ObjectName 128 | , ObjectType 129 | , ParentObjectType 130 | , ObjectPath 131 | --, CBASEDEF_BASE64 132 | , CBASEDEF_COMPRESSED 133 | --, cast(cbasedef_compressed as varchar(max)) as CBASEDEF_COMPRESSED_vc 134 | , CASE CAST(LEFT(CBASEDEF_COMPRESSED, 4) AS VARBINARY(MAX)) 135 | WHEN 0x1F8B0800 THEN 'GZIP' 136 | WHEN 0x504B0304 THEN 'ZIP' 137 | END AS FILE_TYPE 138 | , CASE CAST(LEFT(CBASEDEF_COMPRESSED, 2) AS VARBINARY(MAX)) 139 | WHEN 0x1F8B 140 | THEN CONVERT(VARCHAR(MAX), DECOMPRESS (CBASEDEF_COMPRESSED)) 141 | WHEN 0x504B 142 | THEN 'TODO: UNZIP PKZIP BINARY' 143 | END as CBASEDEF_STRING 144 | 145 | into #outputs 146 | 147 | from zip 148 | 149 | order by ObjectPath 150 | 151 | /* 152 | model CMOBJPROPS7.CMODEL 153 | package (model contains spec) 154 | module CMOBJPROPS86.CBASEDEF 155 | 156 | 157 | TODO: 158 | unzip ZIP binary 159 | extract data source(s) from models (xml) 160 | extract data source(s) from modules (json) 161 | 162 | drop table #zip 163 | 164 | */ 165 | 166 | 167 | /* ************************************************************************* */ 168 | /* ************************************************************************* */ 169 | 170 | /* 171 | Now let's go find all of the models that use specific data sources. 172 | */ 173 | select o.ObjectId 174 | , o.ObjectName 175 | , o.ObjectPath 176 | , cast(o.CBASEDEF_STRING as xml) as CBASEDEF_STRING_x 177 | into #models 178 | from #outputs o 179 | where o.FILE_TYPE = 'GZIP' 180 | and o.ObjectType = 'model' 181 | 182 | ; 183 | WITH 184 | --XMLNAMESPACES ('http://www.developer.cognos.com/schemas/bmt/60/12' as ns) 185 | ----('http://www.developer.cognos.com/schemas/bmt/60/7' as ns) -- The version differs per object. Can we somehow ignore the xml namespace and still get results? *: to the rescue! 186 | --, 187 | models as ( 188 | select o.ObjectId 189 | , o.ObjectPath 190 | --, model.datasource.value('ns:cmDataSource[1]', 'varchar(255)') as DataSource 191 | , model.datasource.value('*:cmDataSource[1]', 'varchar(255)') as DataSource -- *: namespace-unaware in XPath2.0 "This would not work with elements in the default namespace, though." - Rafael Winterhalter on SO 192 | --, model.datasource.value('*[local-name() = "cmDataSource"][1]', 'varchar(255)') as DataSource -- older xpath 193 | from #models o 194 | --cross apply o.CBASEDEF_STRING_x.nodes('/ns:project/ns:dataSources/ns:dataSource') as model(datasource) 195 | cross apply o.CBASEDEF_STRING_x.nodes('/*:project/*:dataSources/*:dataSource') as model(datasource) 196 | --cross apply o.CBASEDEF_STRING_x.nodes('/*[local-name() = "project"]/*[local-name() = "dataSources"]/*[local-name() = "dataSource"]') as model(datasource) 197 | ) 198 | select * 199 | from models 200 | where DataSource in ( 201 | 'My Data Source' 202 | , 'My Other Data Source' 203 | ) 204 | order by 2, 3 205 | 206 | /* ************************************************************************* */ 207 | /* ************************************************************************* */ 208 | 209 | 210 | drop table #models 211 | drop table #outputs 212 | -------------------------------------------------------------------------------- /ContentStore/ModulesAndPackages.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Get specs (.xml and .json files) for packages and data modules. 4 | 5 | .DESCRIPTION 6 | Works for a Cognos Analytics content store on SQL Server 7 | 8 | .PARAMETER CSServerName 9 | Name of the database server where the Content Store lives. 10 | 11 | .PARAMETER CSDatabaseName 12 | Name of the Content Store database. Typically IBMCognos. 13 | 14 | .PARAMETER DirectoryNamespace 15 | Name of the external directory namespace. This is used for the paths of 16 | packages and data modules that are in My Content. 17 | 18 | .EXAMPLE 19 | .\ModulesAndPackages.ps1 "DatabaseServer" "IBMCognos" "DirectoryNamespace" 20 | #> 21 | [CmdletBinding()] 22 | param( 23 | [parameter(position=0, mandatory=$true)] 24 | [string]$CSServerName, 25 | [parameter(position=1, mandatory=$true)] 26 | [string]$CSDatabaseName, 27 | [parameter(position=2, mandatory=$true)] 28 | [string]$DirectoryNamespace 29 | ) 30 | 31 | # $functions = Join-Path $env:USERPROFILE "repos\CognosAdmin\RESTAPI\fn.ps1" 32 | # . $functions 33 | 34 | $sqlquery = " 35 | declare @DirectoryNamespace varchar(255) = '$DirectoryNamespace' 36 | declare @DirectoryNamespaceLength int = 11 37 | -- data container full path 38 | -- ...for all packages, modules, uploaded files, and datasets 39 | ; 40 | with 41 | objname as ( 42 | select o.CMID 43 | , coalesce(n2.name, n.NAME) as 'NAME' 44 | from CMOBJECTS o 45 | left outer join CMOBJNAMES n on n.CMID = o.CMID 46 | and n.LOCALEID = 92 47 | left outer join CMOBJNAMES n2 on n2.CMID = o.CMID 48 | and n2.LOCALEID = 118 49 | ), 50 | package ( 51 | PCMID 52 | , CMID 53 | , ObjectId 54 | , ObjectName 55 | , ObjectPath 56 | , done 57 | , RootNode 58 | , ObjectType 59 | , ParentObjectType 60 | ) as ( 61 | select o.PCMID 62 | , n.CMID 63 | , n.CMID 64 | , cast(n.NAME as varchar(550)) 65 | , cast(n.NAME as varchar(max)) 66 | , 0 67 | , cast(n.NAME as varchar(max)) 68 | , c.NAME 69 | , cast(null as varchar(50)) 70 | from CMOBJECTS o 71 | inner join objname n on n.CMID = o.CMID 72 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 73 | --where c.name in ('package', 'module', 'uploadedFile', 'dataSet2') 74 | where c.name in ('module', 'model') 75 | -- and n.NAME in ('! BigBudgetModule', 'May New data module') 76 | --where c.name = 'model' 77 | -- and n.NAME = 'MS2 Validation' 78 | 79 | union all 80 | select o.PCMID 81 | , n.CMID 82 | , p.ObjectId 83 | , cast( 84 | case 85 | when p.ParentObjectType is null 86 | then 87 | case 88 | when c.NAME = 'folder' 89 | then p.ObjectName 90 | when c.NAME = 'package' 91 | then n.NAME 92 | when c.NAME = 'exploration' 93 | then n.NAME + '--' + p.ObjectName 94 | end 95 | else p.ObjectName 96 | end as varchar(550)) 97 | , case 98 | when p.ParentObjectType is null and c.NAME = 'package' 99 | then cast(n.NAME as varchar(max)) 100 | else cast(n.NAME + '/' + p.ObjectPath as varchar(max)) 101 | end 102 | , case when left(n.NAME, @DirectoryNamespaceLength + 1) = @DirectoryNamespace + ':' then 1 else 0 end 103 | , cast(n.NAME as varchar(max)) 104 | , p.ObjectType 105 | , case when p.ParentObjectType is null then c.NAME else p.ParentObjectType end 106 | from CMOBJECTS o 107 | inner join objname n on n.CMID = o.CMID 108 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 109 | inner join package p on p.PCMID = n.CMID 110 | where n.CMID != 0 111 | and p.done = 0 112 | ), 113 | content as ( 114 | -- There will be many paths for the same object. 115 | -- Keep only the path for each that starts at the root. 116 | select p.ObjectId 117 | , p.ObjectName 118 | , p.ObjectType 119 | , replace(replace(p.ObjectPath, p.RootNode, isnull(u.Name, p.RootNode)), '/(en) ', '/') as ObjectPath 120 | , p.ParentObjectType 121 | 122 | from package p 123 | left outer join ( 124 | select a.OBJID 125 | , b.NAME 126 | 127 | from CMOBJPROPS1 a 128 | inner join CMOBJPROPS33 b on b.CMID = a.CMID 129 | ) u on u.OBJID = p.RootNode 130 | where (p.ObjectPath like 'Team Content%' 131 | or p.ObjectPath like @DirectoryNamespace + ':u:%') 132 | ), 133 | objprops86 as ( 134 | select s.CMID 135 | , cast(s.CBASEDEF as varchar(max)) as CBASEDEF 136 | from CMOBJPROPS86 s 137 | ), 138 | zip as ( 139 | select 140 | d.ObjectId 141 | , d.ObjectName 142 | , d.ObjectType 143 | , d.ParentObjectType 144 | , d.ObjectPath 145 | --, module.CBASEDEF AS CBASEDEF_BASE64 146 | , case d.ObjectType 147 | when 'module' then CAST('' AS XML).value('xs:base64Binary(sql:column(`"module.CBASEDEF`"))', 'VARBINARY(MAX)') 148 | when 'model' then cast(model.cmodel as varbinary(max)) 149 | end as CBASEDEF_COMPRESSED 150 | from content d 151 | left outer join objprops86 module on module.CMID = d.ObjectId 152 | left outer join CMOBJPROPS7 model on model.CMID = d.ObjectId 153 | ) 154 | 155 | select 156 | ObjectId 157 | , ObjectName 158 | , ObjectType 159 | , ParentObjectType 160 | , ObjectPath 161 | --, CBASEDEF_BASE64 162 | , CBASEDEF_COMPRESSED 163 | --, cast(cbasedef_compressed as varchar(max)) as CBASEDEF_COMPRESSED_vc 164 | , CASE CAST(LEFT(CBASEDEF_COMPRESSED, 4) AS VARBINARY(MAX)) 165 | WHEN 0x1F8B0800 THEN 'GZIP' 166 | WHEN 0x504B0304 THEN 'ZIP' 167 | END AS FILE_TYPE 168 | , CASE CAST(LEFT(CBASEDEF_COMPRESSED, 2) AS VARBINARY(MAX)) 169 | WHEN 0x1F8B 170 | THEN CONVERT(VARCHAR(MAX), DECOMPRESS (CBASEDEF_COMPRESSED)) 171 | WHEN 0x504B 172 | THEN 'TODO: UNZIP PKZIP BINARY' 173 | END as CBASEDEF_STRING 174 | 175 | --into #outputs 176 | 177 | from zip 178 | 179 | order by ObjectPath" 180 | 181 | Write-Host " 182 | 183 | 184 | 185 | starting 186 | " 187 | 188 | $result = Invoke-Sqlcmd -Query $sqlquery ` 189 | -ServerInstance $CSServerName ` 190 | -Database $CSDatabaseName ` 191 | -MaxCharLength 25000000 ` 192 | -ConnectionTimeout 10 ` 193 | -QueryTimeout 600 ` 194 | -TrustServerCertificate 195 | 196 | Write-Host "got data... continuing" 197 | 198 | $zipPath = Join-Path $env:USERPROFILE "temp.zip" 199 | $zipFolderPath = Join-Path $env:USERPROFILE "temp" 200 | $basePath = Join-Path $env:USERPROFILE "CognosModules" 201 | 202 | $basePath | Get-ChildItem -Recurse | Remove-Item -Recurse 203 | 204 | # $modules = @() 205 | $l = $result.length 206 | $i = 0 207 | $startTime = Get-Date 208 | 209 | $modulesToUnzip = 0 210 | $modulesUnzipped = 0 211 | 212 | # Write-Host "starting loop 213 | 214 | # " 215 | 216 | foreach ($row in $result) { 217 | # Write-Host $row.ObjectName 218 | 219 | # $r = [PSCustomObject]@{} 220 | if ($row.ObjectPath -like "Team Content/*") { 221 | $objPath = $row.ObjectPath 222 | # $r | Add-Member -MemberType NoteProperty -Name 'ObjectPath' -Value $row.ObjectPath 223 | } 224 | else { 225 | $objPath = Join-Path "My Content" $row.ObjectPath 226 | # $r | Add-Member -MemberType NoteProperty -Name 'ObjectPath' -Value $objPath 227 | } 228 | # $r | Add-Member -MemberType NoteProperty -Name 'ObjectType' -Value $row.ObjectType 229 | # $r | Add-Member -MemberType NoteProperty -Name 'FileType' -Value $row.FILE_TYPE 230 | # $r | Add-Member -MemberType NoteProperty -Name 'CBASEDEF_COMPRESSED' -Value $row.CBASEDEF_COMPRESSED 231 | 232 | if ($row.CBASEDEF_STRING -eq "TODO: UNZIP PKZIP BINARY") { 233 | # Write-Host " unzipping" 234 | $modulesToUnzip++ 235 | $binary = $row.CBASEDEF_COMPRESSED 236 | $binary | Set-Content -Path $zipPath -AsByteStream 237 | try { 238 | # Write-Host " expanding" 239 | Expand-Archive -Path $zipPath -DestinationPath $zipFolderPath 240 | # Write-Host " expanded" 241 | $files = Get-ChildItem -Path $zipFolderPath 242 | $baseDef = Get-Content $files.FullName 243 | Remove-Item -Path $zipFolderPath -Recurse 244 | $modulesUnzipped++ 245 | } 246 | catch { 247 | # Write-Host " failed to expand: $($row.ObjectPath)" 248 | $baseDef = "" 249 | } 250 | 251 | # $r | Add-Member -MemberType NoteProperty -Name 'CBASEDEF_STRING' -Value $baseDef 252 | } 253 | else { 254 | $baseDef = $row.CBASEDEF_STRING 255 | # $r | Add-Member -MemberType NoteProperty -Name 'CBASEDEF_STRING' -Value $row.CBASEDEF_STRING 256 | } 257 | 258 | if ($row.ObjectType -eq "module" -and $row.FILE_TYPE -eq "GZIP") { 259 | # $r | Add-Member -MemberType NoteProperty -Name 'FileExt' -Value ".json" 260 | $fileExt = ".json" 261 | # Depth defaults 262 | # ConvertFrom-Json = 1024 263 | # ConvertTo-Json = 2 (max = 100) 264 | $baseDef = $baseDef | ConvertFrom-Json | ConvertTo-Json -Depth 100 265 | } 266 | else { 267 | # $r | Add-Member -MemberType NoteProperty -Name 'FileExt' -Value ".xml" 268 | $fileExt = ".xml" 269 | $baseDef =$baseDef | Format-XML 270 | } 271 | 272 | # $modules += $r 273 | 274 | $relPath = "$($objPath)$($fileExt)" 275 | $filePath = Join-Path $basePath $relPath 276 | $folderPath = Split-Path $filePath 277 | # Write-Host " writing file" 278 | if (!(Test-Path $folderPath)) { 279 | # Write-Host " $folderPath does not exist" 280 | New-Item -ItemType Directory -Path $folderPath -Force 281 | } 282 | $baseDef | Out-File -FilePath $filePath 283 | 284 | $i++ 285 | $p = [int]($i * 100 / $l) 286 | 287 | $elapsed = ((Get-Date) - $startTime).TotalSeconds 288 | $remainingItems = $l - $i 289 | $averageItemTime = $elapsed / $i 290 | 291 | Write-Progress "Processing $l modules" -Status "$i modules processed" -PercentComplete $p -SecondsRemaining ($remainingItems * $averageItemTime) 292 | } 293 | 294 | Write-Host "Total number of modules: $l" 295 | Write-Host "Modules to unzip: $modulesToUnzip" 296 | Write-Host "Modules successfully unzipped: $modulesUnzipped" 297 | -------------------------------------------------------------------------------- /ContentStore/OutputSpecs.sql: -------------------------------------------------------------------------------- 1 | ; 2 | with cte2(CMID, 3 | ObjectName, 4 | ObjectPath, 5 | ObjectClass, 6 | Modified) as 7 | ( 8 | select o.CMID 9 | , n.NAME 10 | , cast( 11 | replace( 12 | replace( 13 | replace( 14 | replace( 15 | replace( 16 | replace( 17 | replace( 18 | replace( 19 | replace( 20 | n.NAME, char(60), '' -- < 21 | ), char(62), '' -- > 22 | ), char(58), '' -- : 23 | ), char(34), '' -- quote 24 | ), char(47), '' -- / 25 | ), char(92), '' -- \ 26 | ), char(124), '' -- | 27 | ), char(63), '' -- ? 28 | ), char(42), '' -- * 29 | ) as varchar(max)) 30 | , cast(c.NAME as varchar(max)) 31 | , o.MODIFIED 32 | from CMOBJECTS o 33 | inner join CMOBJNAMES n on n.CMID = o.CMID 34 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 35 | where n.ISDEFAULT = 1 36 | and isdate(n.NAME) = 0 37 | and o.CMID = 2 38 | 39 | union all 40 | select o.CMID 41 | , n.NAME 42 | , cast(cte2.ObjectPath + '/' + 43 | replace( 44 | replace( 45 | replace( 46 | replace( 47 | replace( 48 | replace( 49 | replace( 50 | replace( 51 | replace( 52 | n.NAME, char(60), '' 53 | ), char(62), '' 54 | ), char(58), '' 55 | ), char(34), '' 56 | ), char(47), '' 57 | ), char(92), '' 58 | ), char(124), '' 59 | ), char(63), '' 60 | ), char(42), '' 61 | ) as varchar(max)) 62 | , cast(c.NAME as varchar(max)) 63 | , o.MODIFIED 64 | from CMOBJECTS o 65 | inner join CMOBJNAMES n on n.CMID = o.CMID 66 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 67 | inner join cte2 cte2 on cte2.CMID = o.PCMID 68 | where n.ISDEFAULT = 1 69 | and n.CMID != 0 70 | ) 71 | 72 | select REPLACE(c.ObjectPath,'/','\') + case when c.ObjectClass = 'exploration' then '.json' else '.xml' end as FilePath 73 | , s.SPEC as SPEC 74 | from cte2 c 75 | left join CMOBJPROPS7 s on s.CMID = c.CMID 76 | where c.ObjectClass in ('report', 'exploration', 'dataSet2') 77 | and c.ObjectPath like 'Team Content/Reports%' -------------------------------------------------------------------------------- /ContentStore/OwnedObjects.sql: -------------------------------------------------------------------------------- 1 | -- objects owned by the selected user 2 | ; 3 | declare @DirectoryNamespace varchar(255) = '$AuthenticationNamespace' 4 | declare @username nvarchar(256) = N'username' 5 | ; 6 | with 7 | objname as ( 8 | select o.CMID 9 | , coalesce(n2.name, n.NAME) as 'NAME' 10 | from CMOBJECTS o 11 | left outer join CMOBJNAMES n on n.CMID = o.CMID 12 | and n.LOCALEID = 92 -- en 13 | left outer join CMOBJNAMES n2 on n2.CMID = o.CMID 14 | and n2.LOCALEID = 118 -- en-us 15 | ), 16 | usr as ( 17 | select u.CMID 18 | from CMOBJPROPS33 u 19 | where u.NAME = @username 20 | ), 21 | userobjects as ( 22 | select o.CMID 23 | , o.MODIFIED 24 | , o.OWNER 25 | , n.NAME 26 | , c.NAME as Class 27 | , po.CMID as ParentCMID 28 | , po.OWNER as ParentOwner 29 | , pn.NAME as ParentName 30 | , pc.NAME as ParentClass 31 | from CMOBJECTS o 32 | inner join objname n on n.CMID = o.CMID 33 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 34 | inner join CMREFNOORD2 n2 on n2.CMID = o.CMID 35 | inner join CMOBJECTS po on po.CMID = o.PCMID 36 | inner join objname pn on pn.CMID = po.CMID 37 | inner join CMCLASSES pc on pc.CLASSID = po.CLASSID 38 | inner join usr u on u.CMID = n2.REFCMID 39 | ), 40 | cte( 41 | PCMID, 42 | CMID, 43 | ObjectId, 44 | ObjectName, 45 | ObjectPath, 46 | done, 47 | RootNode, 48 | ObjectClass 49 | ) as ( 50 | select o.PCMID 51 | , n.CMID 52 | , n.CMID 53 | , n.NAME 54 | , cast(n.NAME as varchar(max)) 55 | , 0 56 | , cast(n.NAME as varchar(max)) 57 | , c.NAME 58 | from CMOBJECTS o 59 | inner join objname n on n.CMID = o.CMID 60 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 61 | inner join userobjects uo on uo.CMID = o.CMID 62 | 63 | union all 64 | select o.PCMID 65 | , n.CMID 66 | , cte.ObjectId 67 | , cte.ObjectName 68 | , cast(n.NAME + '/' + cte.ObjectPath as varchar(max)) 69 | , case when left(n.NAME, 8) = @DirectoryNamespace + ':' then 1 else 0 end 70 | , cast(n.NAME as varchar(max)) 71 | , cte.ObjectClass 72 | from CMOBJECTS o 73 | inner join objname n on n.CMID = o.CMID 74 | inner join cte cte on cte.PCMID = n.CMID 75 | where n.CMID != 0 76 | and cte.done = 0 77 | ) 78 | 79 | select c.ObjectId 80 | , c.ObjectName 81 | , replace(c.ObjectPath, c.RootNode, isnull(u.Name, c.RootNode)) as ObjectPath 82 | , c.ObjectClass 83 | into #reports 84 | from cte c 85 | left outer join ( 86 | select a.OBJID 87 | , b.NAME 88 | 89 | from CMOBJPROPS1 a 90 | inner join CMOBJPROPS33 b on b.CMID = a.CMID 91 | ) u on u.OBJID = c.RootNode 92 | where (c.ObjectPath like 'Team Content%' 93 | or c.ObjectPath like @DirectoryNamespace + ':%') 94 | order by ObjectPath 95 | 96 | select * 97 | from #reports 98 | order by ObjectPath 99 | 100 | drop table #reports 101 | -------------------------------------------------------------------------------- /ContentStore/PackageReference.sql: -------------------------------------------------------------------------------- 1 | -- find data containers (packages, modules, uploaded files, and datasets) that are not used 2 | use IBMCognos 3 | GO 4 | /* 5 | Package Usage 6 | Are packages used? (by existing presentation outputs) 7 | */ 8 | ; 9 | declare @DirectoryNamespace varchar(255) = 'MyNamespace' 10 | declare @DirectoryNamespaceLength int = 11 11 | 12 | 13 | -- output object full path 14 | -- ...for all reports and dashboards 15 | ; 16 | with 17 | objname as ( 18 | select o.CMID 19 | , coalesce(n2.name, n.NAME) as 'NAME' 20 | --, n.NAME 21 | --, n2.NAME 22 | from CMOBJECTS o 23 | left outer join CMOBJNAMES n on n.CMID = o.CMID 24 | and n.LOCALEID = 92 25 | left outer join CMOBJNAMES n2 on n2.CMID = o.CMID 26 | and n2.LOCALEID = 118 27 | --order by 2 28 | ), 29 | report (PCMID, 30 | CMID, 31 | ObjectId, 32 | ObjectName, 33 | ObjectPath, 34 | PackageId, 35 | done, 36 | RootNode, 37 | ObjectType) as ( 38 | -- reports 39 | select o.PCMID 40 | , n.CMID 41 | , n.CMID 42 | , n.NAME 43 | , cast(n.NAME as varchar(max)) 44 | , r.REFCMID as PackageId 45 | , 0 46 | , cast(n.NAME as varchar(max)) 47 | , c.NAME 48 | from CMOBJECTS o 49 | inner join objname n on n.CMID = o.CMID 50 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 51 | inner join CMREFNOORD1 r on r.CMID = o.CMID -- to get package 52 | where c.name = 'report' 53 | --and n.NAME like '%deer%' 54 | 55 | union all 56 | -- dashboards 57 | select o.PCMID 58 | , n.CMID 59 | , n.CMID 60 | , n.NAME 61 | , cast(n.NAME as varchar(max)) 62 | , r.REFCMID as PackageId 63 | , 0 64 | , cast(n.NAME as varchar(max)) 65 | , c.NAME 66 | from CMOBJECTS o 67 | inner join objname n on n.CMID = o.CMID 68 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 69 | inner join CMREFORD1 r on r.CMID = o.CMID -- to get package 70 | where c.name = 'exploration' 71 | --and n.NAME like '%daily spend%' 72 | 73 | union all 74 | -- parent folders 75 | select o.PCMID 76 | , n.CMID 77 | , r.ObjectId 78 | , r.ObjectName 79 | , cast(n.NAME + '/' + r.ObjectPath as varchar(max)) 80 | , r.PackageId 81 | , case when left(n.NAME, @DirectoryNamespaceLength + 1) = @DirectoryNamespace + ':' then 1 else 0 end 82 | , cast(n.NAME as varchar(max)) 83 | , r.ObjectType 84 | from CMOBJECTS o 85 | inner join objname n on n.CMID = o.CMID 86 | inner join report r on r.PCMID = n.CMID 87 | where n.CMID != 0 88 | and r.done = 0 89 | ) 90 | 91 | -- There will be many paths for the same object. 92 | -- Keep only the path for each that starts at the root. 93 | select r.ObjectId 94 | , r.ObjectName 95 | , r.ObjectType 96 | , replace(replace(r.ObjectPath, r.RootNode, isnull(u.Name, r.RootNode)), '/(en) ', '/') as ObjectPath 97 | , r.PackageId 98 | into #output 99 | from report r 100 | left outer join ( 101 | select a.OBJID 102 | , b.NAME 103 | 104 | from CMOBJPROPS1 a 105 | inner join CMOBJPROPS33 b on b.CMID = a.CMID 106 | ) u on u.OBJID = r.RootNode 107 | where (r.ObjectPath like 'Team Content%' 108 | or r.ObjectPath like @DirectoryNamespace + ':%') 109 | order by ObjectPath 110 | ; 111 | 112 | -- data container full path 113 | -- ...for all packages, modules, uploaded files, and datasets 114 | with 115 | objname as ( 116 | select o.CMID 117 | , coalesce(n2.name, n.NAME) as 'NAME' 118 | --, n.NAME 119 | --, n2.NAME 120 | from CMOBJECTS o 121 | left outer join CMOBJNAMES n on n.CMID = o.CMID 122 | and n.LOCALEID = 92 123 | left outer join CMOBJNAMES n2 on n2.CMID = o.CMID 124 | and n2.LOCALEID = 118 125 | --order by 2 126 | ), 127 | package (PCMID, 128 | CMID, 129 | ObjectId, 130 | ObjectName, 131 | ObjectPath, 132 | done, 133 | RootNode, 134 | ObjectType) as ( 135 | select o.PCMID 136 | , n.CMID 137 | , n.CMID 138 | , n.NAME 139 | , cast(n.NAME as varchar(max)) 140 | , 0 141 | , cast(n.NAME as varchar(max)) 142 | , c.NAME 143 | from CMOBJECTS o 144 | inner join objname n on n.CMID = o.CMID 145 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 146 | where c.name in ('package', 'module', 'uploadedFile', 'dataSet2') 147 | --and n.NAME like '%factless%' 148 | 149 | union all 150 | select o.PCMID 151 | , n.CMID 152 | , p.ObjectId 153 | , p.ObjectName 154 | , cast(n.NAME + '/' + p.ObjectPath as varchar(max)) 155 | , case when left(n.NAME, @DirectoryNamespaceLength + 1) = @DirectoryNamespace + ':' then 1 else 0 end 156 | , cast(n.NAME as varchar(max)) 157 | , p.ObjectType 158 | from CMOBJECTS o 159 | inner join objname n on n.CMID = o.CMID 160 | inner join package p on p.PCMID = n.CMID 161 | where n.CMID != 0 162 | and p.done = 0 163 | ) 164 | 165 | -- There will be many paths for the same object. 166 | -- Keep only the path for each that starts at the root. 167 | select p.ObjectId 168 | , p.ObjectName 169 | , p.ObjectType 170 | , replace(replace(p.ObjectPath, p.RootNode, isnull(u.Name, p.RootNode)), '/(en) ', '/') as ObjectPath 171 | into #data 172 | from package p 173 | left outer join ( 174 | select a.OBJID 175 | , b.NAME 176 | 177 | from CMOBJPROPS1 a 178 | inner join CMOBJPROPS33 b on b.CMID = a.CMID 179 | ) u on u.OBJID = p.RootNode 180 | where (p.ObjectPath like 'Team Content%' 181 | or p.ObjectPath like @DirectoryNamespace + ':%') 182 | order by ObjectPath 183 | ; 184 | 185 | 186 | -- Identify all instances where a data container uses another data container. 187 | ; 188 | with 189 | subpackages as ( 190 | select p.ObjectId as PackageId 191 | , p.ObjectPath as PackagePath 192 | , p.ObjectType as PackageType 193 | , sp.ObjectId as SubPackageId 194 | , sp.ObjectPath as SubPackagePath 195 | , sp.ObjectType as SubPackageType 196 | , 0 as depth 197 | 198 | from #data p 199 | left outer join CMREFORD1 ro on ro.CMID = p.ObjectId 200 | left outer join #data sp on sp.ObjectId = ro.REFCMID 201 | 202 | union all 203 | -- "packages" per data module 204 | select p.PackageId 205 | , p.PackagePath 206 | , p.PackageType 207 | , sp.ObjectId as SubPackageId 208 | , sp.ObjectPath as SubPackagePath 209 | , sp.ObjectType as SubPackageType 210 | , p.depth + 1 211 | 212 | from subpackages p 213 | inner join CMREFORD1 ro on ro.CMID = p.SubPackageId 214 | inner join #data sp on sp.ObjectId = ro.REFCMID 215 | where p.depth < 7 -- because of self-referencing data modules 216 | 217 | union all 218 | -- "packages" per dataset 219 | select p.PackageId 220 | , p.PackagePath 221 | , p.PackageType 222 | , sp.ObjectId as SubPackageId 223 | , sp.ObjectPath as SubPackagePath 224 | , sp.ObjectType as SubPackageType 225 | , p.depth + 1 226 | 227 | from subpackages p 228 | inner join CMREFNOORD1 rno on rno.CMID = p.PackageId 229 | inner join #data sp on sp.ObjectId = rno.REFCMID 230 | where p.depth < 7 -- because of self-referencing data modules 231 | ) 232 | 233 | select distinct PackageId 234 | , PackagePath 235 | , PackageType 236 | , SubPackageId 237 | , SubPackagePath 238 | , SubPackageType 239 | into #subdata 240 | from subpackages 241 | 242 | 243 | --select * 244 | --from #subdata 245 | --where PackagePath like 'Team Content/Reports/Traffic Operations/South Central Traffic/Deer Signs/%' 246 | --order by PackageId 247 | --, SubPackageId 248 | 249 | -- Show all data containers 250 | -- Recursively attribute usage to subcontainers 251 | ; 252 | with 253 | scusage as ( 254 | select distinct d.PackageId 255 | , d.PackagePath 256 | , d.PackageType 257 | --, d.SubPackageId 258 | --, d.SubPackagePath 259 | --, d.SubPackageType 260 | , o.ObjectId 261 | , o.ObjectName 262 | , o.ObjectPath 263 | , o.ObjectType 264 | , 0 as depth 265 | from #subdata d 266 | inner join #output o on o.PackageId = d.PackageId 267 | 268 | union all 269 | select sd.PackageId 270 | , sd.PackagePath 271 | , sd.PackageType 272 | , u.ObjectId 273 | , u.ObjectName 274 | , u.ObjectPath 275 | , u.ObjectType 276 | , u.depth + 1 277 | from #subdata sd 278 | inner join #subdata d on d.SubPackageId = sd.PackageId 279 | inner join scusage u on u.PackageId = d.PackageId 280 | where u.depth < 3 281 | ) 282 | 283 | select distinct PackageId 284 | , PackagePath 285 | , PackageType 286 | , ObjectId 287 | , ObjectName 288 | , ObjectPath 289 | , ObjectType 290 | into #scusage 291 | from scusage 292 | order by PackagePath 293 | , ObjectPath 294 | 295 | 296 | 297 | -- Show all data containers and the output objects that use them. 298 | select * 299 | from #scusage 300 | order by PackagePath 301 | , ObjectPath 302 | 303 | 304 | 305 | -- Show all data containers that are not used by any output objects 306 | select distinct d.PackageId 307 | , d.PackagePath 308 | , d.PackageType 309 | from #subdata d 310 | 311 | except 312 | select u.PackageId 313 | , u.PackagePath as UnusedPackagePath 314 | , u.PackageType 315 | from #scusage u 316 | 317 | order by PackagePath 318 | 319 | 320 | /* 321 | drop table #data 322 | drop table #output 323 | drop table #subdata 324 | drop table #scusage 325 | */ 326 | -------------------------------------------------------------------------------- /ContentStore/PermissionsPerUser.sql: -------------------------------------------------------------------------------- 1 | 2 | declare @CognosUserName varchar(max) = 'Hyperion Collision Power User' 3 | declare @CognosUserType varchar(max) = 'group' 4 | 5 | declare @querystring nvarchar(max) = 'SELECT ''WSDOTAD:' + left(@CognosUserType, 1) + ':'' + convert(varchar(max), ObjectGUID, 2) as ObjectGUID 6 | FROM OpenQuery ( 7 | ADSI, 8 | ''SELECT sAMAccountName, ObjectGUID 9 | FROM ''''LDAP://WSDOT.LOC/DC=WSDOT,DC=LOC'''' 10 | WHERE objectClass = ''''' + @CognosUserType + ''''' 11 | and sAMAccountName = ''''' + @CognosUserName + ''''' 12 | '' 13 | ) A' 14 | 15 | declare @ObjectGUID table ( 16 | ObjectGUID varchar(max) 17 | ) 18 | insert into @ObjectGUID 19 | exec sp_executesql @querystring 20 | 21 | declare @pol table ( 22 | CMID int, 23 | POLICIES varbinary(max) 24 | ) 25 | 26 | declare @b64 table ( 27 | id int identity(1,1) not null, 28 | cmid int, 29 | POLICIES varchar(max), 30 | PolicyReadable varchar(max) 31 | ) 32 | 33 | declare @heirarchy table ( 34 | CMID int, 35 | ObjectName varchar(max), 36 | ObjectPath varchar(max) 37 | ) 38 | 39 | insert @pol 40 | select CMID 41 | , cast(POLICIES as varbinary(max)) as POLICIES 42 | from CMPOLICIES 43 | WHERE POLICIES IS NOT NULL 44 | --and cmid = 2525 45 | --and cmid = 2339 46 | ; 47 | 48 | insert @b64 (cmid, POLICIES) 49 | select cmid, 50 | cast('' as xml).value( 51 | 'xs:base64Binary(sql:column("@pol.POLICIES"))', 'varchar(max)' 52 | ) AS POLICIES 53 | from @pol 54 | ; 55 | 56 | with 57 | src ( 58 | CMID, 59 | ObjectName, 60 | ObjectPath) as 61 | ( 62 | select o.CMID 63 | , n.NAME 64 | , cast(n.NAME as varchar(max)) 65 | from CMOBJECTS o 66 | inner join CMOBJNAMES n on n.CMID = o.CMID 67 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 68 | where n.ISDEFAULT = 1 69 | and isdate(n.NAME) = 0 70 | and o.CMID = 2 71 | 72 | union all 73 | select o.CMID 74 | , n.NAME 75 | , cast(src.ObjectPath + '/' + n.NAME as varchar(max)) 76 | from CMOBJECTS o 77 | inner join CMOBJNAMES n on n.CMID = o.CMID 78 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 79 | inner join src on src.CMID = o.PCMID 80 | where n.ISDEFAULT = 1 81 | and n.CMID != 0 82 | ) 83 | insert into @heirarchy 84 | select * 85 | from src 86 | ; 87 | 88 | declare @j int = 1 89 | declare @jMax int 90 | select @jMax = id 91 | from @b64 92 | 93 | while @j <= @jMax 94 | begin 95 | update @b64 96 | set PolicyReadable = dbo.udf_CognosPermissions(POLICIES) 97 | where id = @j 98 | 99 | set @j = @j + 1 100 | end 101 | 102 | 103 | select o.* 104 | , b.PolicyReadable 105 | from @heirarchy o 106 | inner join @b64 b on b.CMID = o.CMID 107 | inner join @ObjectGUID g on b.PolicyReadable like '%' + g.ObjectGUID + '%' 108 | order by ObjectPath 109 | 110 | -------------------------------------------------------------------------------- /ContentStore/README.md: -------------------------------------------------------------------------------- 1 | # Cognos Content Store Database 2 | Cognos stores most content in this database. 3 | 4 | I use Microsoft SQL Server. Your mileage may vary. 5 | 6 | Hacking the Cognos Content Store database is not recommended. The correct, supported way to automate Cognos management tasks is by using the Cognos SDK. 7 | 8 | ### ContentStore.txt 9 | 10 | Listing and description of tables in the Content Store database. Found on Cognoise.com. Comments updated as new insights are realized. 11 | 12 | ### ContentStoreCMIDSearch.sql 13 | 14 | Listing and description of tables in the Content Store database. Found on Cognoise.com. Comments updated as new insights are realized. 15 | Limited and formatted specifically for searching for a specific CMID. 16 | 17 | ### CognosScheduleEmailRecipients.sql 18 | 19 | Lists email recipients for schedules. 20 | 21 | ### LocateSchedules.sql 22 | 23 | Outputs the path to each schedule. 24 | 25 | ### OutputSpecs.sql 26 | 27 | Output specifications for reports, dashboards, and data sets within Team Content with the folder structure seen in Cognos. This can be used as part of a routine to write to the file system. 28 | 29 | ### SpecBackup (folder) 30 | 31 | Output specifications for reports, dashboards, and data sets to the file system and push them to a source control repository. 32 | 33 | ### BrokenShortcuts.sql 34 | 35 | Find broken shortcuts and report views. 36 | 37 | ### OwnedObjects.sql 38 | 39 | See which objects a user owns. 40 | 41 | ### PackageReference.sql 42 | 43 | Identifies data containers (packages, data modules, etc.) and which presentation objects (reports, dashboards, etc.) use them. 44 | Also identifies data containers that are not used. 45 | Identifies where a data module uses a dataset that is populated from a data module that uses a dataset that uses a package (etc.) 46 | and attributes the usage (presentation object) to the parent data container. 47 | Whether or not the presentation objects have been used is a different question. This routine considers only object references, not usage stats from the Audit database. 48 | 49 | ### ModuleAndModelSpecs.sql 50 | 51 | Initially intended to allow a system-wide search for packages and models that use a specific data source. 52 | 53 | ### ModulesAndPackages.ps1 54 | 55 | Queries the Content Store and saves specs of packages and data modules to the file system. Includes prettifying the json or xml for easy diffs in source control. 56 | This script has trouble unzipping some PKZipped data. It reports the number of objects that require unzipping and the number of objects unzipped. 57 | 58 | 59 | ## Permissions 60 | 61 | ### SQL-Only 62 | 63 | #### PermissionsPerUser.sql 64 | 65 | Find everywhere that a user (or group) from Active Directory is defined in object permissions in Cognos. 66 | 67 | For objects that inherit permissions, POLICIES is NULL. These are not identified by this query. 68 | 69 | This query processes the CMPOLICIES.POLICIES value for all objects in the Content Store using two, nested functions, then performs the search (filter) on the results. It can take a very long time to run. 70 | 71 | Requires udf_CognosPermissions.sql and ADSI.sql. 72 | 73 | #### udf_CognosPermissions.sql 74 | 75 | Converts CMPOLICIES.POLICIES (image) to a human-readable string. 76 | 77 | Requires udf_ConvertFromBase10.sql 78 | 79 | #### udf_ConvertFromBase10.sql 80 | 81 | Converts a number in base 10 to a string (varchar(255)) containing the number in another number base. 82 | 83 | Used by udf_CognosPermissions to convert 64-bit encoded characters to binary. 84 | 85 | #### ADSI.sql 86 | 87 | Sets up the linked server to query Active Directory. 88 | 89 | From https://www.mssqltips.com/sqlservertip/2580/querying-active-directory-data-from-sql-server/ 90 | 91 | Make sure you change the @rmtuser and @rmtpassword variables to a login and password that has access to your Active Directory. 92 | 93 | ### SQL and PowerShell 94 | 95 | If you can't create a linked server and a user-defined function, 96 | maybe you'll have the ability to look up the information using PowerShell. 97 | 98 | #### RoleGroupMembership.ps1 99 | 100 | Lists members of all Cognos roles. 101 | 102 | #### ObjectPermissions.ps1 103 | 104 | Lists what permissions users and groups have to each Cognos object within Team Content (CMID=2). 105 | Takes about 5 minutes to run. Our Content Store has about 190,000 rows in CMOBJECTS with about 7,300 objects within the scope of this script. 106 | 107 | #### ObjectCapabilities.ps1 108 | 109 | Lists what permissions (grant or deny) users and groups have to each capability for each Cognos object within Team Content (CMID=2). 110 | Takes about 5 minutes to run. Our Content Store has about 190,000 rows in CMOBJECTS with about 1,250 objects within the scope of this script. 111 | -------------------------------------------------------------------------------- /ContentStore/RoleGroupMembership.ps1: -------------------------------------------------------------------------------- 1 | $CognosEnvironment = Read-Host "Cognos Environment (P, Q, D):" 2 | switch($CognosEnvironment) { 3 | "P" { 4 | $dbServer = "ProdDBServer" 5 | $dbName = "ProdDBName" 6 | } 7 | "Q" { 8 | $dbServer = "QADBServer" 9 | $dbName = "QADBName" 10 | } 11 | "D" { 12 | $dbServer = "DevDBServer" 13 | $dbName = "DevDBName" 14 | } 15 | } 16 | 17 | $AuthenticationNamespace = "NamespaceName" 18 | 19 | " 20 | 21 | 22 | 23 | Getting data from the database. 24 | This may take a couple minutes. 25 | 26 | 27 | 28 | " 29 | 30 | $sqlquery = " 31 | declare @DirectoryNamespace varchar(255) = '$AuthenticationNamespace' 32 | ; 33 | with 34 | objname as ( 35 | select o.CMID 36 | , coalesce(n2.name, n.NAME) as 'NAME' 37 | from CMOBJECTS o 38 | left outer join CMOBJNAMES n on n.CMID = o.CMID 39 | and n.LOCALEID = 92 -- en 40 | left outer join CMOBJNAMES n2 on n2.CMID = o.CMID 41 | and n2.LOCALEID = 118 -- en-us 42 | ), 43 | rolegroup ( 44 | CMID 45 | , ObjectName 46 | , ObjectPath 47 | , ObjectClass 48 | , done 49 | ) as ( 50 | select o.CMID 51 | , n.NAME 52 | , cast(n.NAME as varchar(max)) 53 | , cast(c.NAME as varchar(max)) 54 | , 1 55 | from CMOBJECTS o 56 | inner join objname n on n.CMID = o.CMID 57 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 58 | where n.NAME = 'Cognos' 59 | and c.NAME = 'namespace' 60 | 61 | union all 62 | select o.CMID 63 | , n.NAME 64 | , cast(rg.ObjectPath + '/' + n.NAME as varchar(max)) 65 | , cast(c.NAME as varchar(max)) 66 | , rg.done + 1 67 | from CMOBJECTS o 68 | inner join objname n on n.CMID = o.CMID 69 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 70 | inner join rolegroup rg on rg.CMID = o.PCMID 71 | where n.CMID != 0 72 | and c.NAME in ('namespaceFolder', 'group', 'role') 73 | ), 74 | members as ( 75 | select rg.CMID 76 | , rg.ObjectPath 77 | , rg.ObjectClass 78 | , coalesce(u.NAME, n.NAME) as MemberName 79 | , c.NAME as MemberClass 80 | , o.CMID as MemberCMID 81 | , case when c.NAME = 'group' and n.NAME like @DirectoryNamespace + ':g:%' then 82 | SUBSTRING(n.name, 17, 2) + 83 | SUBSTRING(n.name, 15, 2) + 84 | SUBSTRING(n.name, 13, 2) + 85 | SUBSTRING(n.name, 11, 2) + 86 | '-' + 87 | SUBSTRING(n.name, 21, 2) + 88 | SUBSTRING(n.name, 19, 2) + 89 | '-' + 90 | SUBSTRING(n.name, 25, 2) + 91 | SUBSTRING(n.name, 23, 2) + 92 | '-' + 93 | SUBSTRING(n.name, 27, 4) + 94 | '-' + 95 | SUBSTRING(n.name, 31, 12) 96 | end as MemberObjectGUID 97 | from rolegroup rg 98 | inner join CMREFORD1 r on r.CMID = rg.CMID 99 | inner join CMOBJECTS o on o.CMID = r.REFCMID 100 | inner join objname n on n.CMID = o.CMID 101 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 102 | left outer join CMOBJPROPS33 u on u.CMID = o.CMID 103 | ) 104 | 105 | select * 106 | from members 107 | order by ObjectPath 108 | " 109 | 110 | $result = Invoke-Sqlcmd $sqlquery ` 111 | -ServerInstance $dbServer ` 112 | -Database $dbName ` 113 | -MaxCharLength 1000000 ` 114 | -ConnectionTimeout 10 ` 115 | -QueryTimeout 600 ` 116 | -TrustServerCertificate 117 | 118 | $l = $result.length 119 | $i = 0 120 | $startTime = Get-Date 121 | $out = @() 122 | 123 | foreach($row in $result) { 124 | $o = $row.MemberObjectGUID 125 | if ($o.length -gt 1) { 126 | $filter = "ObjectGUID -eq `"$o`"" 127 | $g = Get-ADGroup -Filter $filter 128 | if ($g) { 129 | $m = Get-ADGroupMember $g -Recursive 130 | foreach ($member in $m) { 131 | $r = [PSCustomObject]@{} 132 | $r | Add-Member -MemberType NoteProperty -Name 'ObjectPath' -Value $row.ObjectPath 133 | $r | Add-Member -MemberType NoteProperty -Name 'ObjectClass' -Value $row.ObjectClass 134 | $r | Add-Member -MemberType NoteProperty -Name 'MemberClass' -Value 'account' 135 | $r | Add-Member -MemberType NoteProperty -Name 'MemberName' -Value $member.Name 136 | $out += $r 137 | } 138 | } 139 | else { 140 | # group not found in MSAD 141 | $r = [PSCustomObject]@{} 142 | $r | Add-Member -MemberType NoteProperty -Name 'ObjectPath' -Value $row.ObjectPath 143 | $r | Add-Member -MemberType NoteProperty -Name 'ObjectClass' -Value $row.ObjectClass 144 | $r | Add-Member -MemberType NoteProperty -Name 'MemberClass' -Value $row.MemberClass 145 | $r | Add-Member -MemberType NoteProperty -Name 'MemberName' -Value $row.MemberName 146 | $out += $r 147 | } 148 | } 149 | else { 150 | # no ObjectGUID provided 151 | $r = [PSCustomObject]@{} 152 | $r | Add-Member -MemberType NoteProperty -Name 'ObjectPath' -Value $row.ObjectPath 153 | $r | Add-Member -MemberType NoteProperty -Name 'ObjectClass' -Value $row.ObjectClass 154 | $r | Add-Member -MemberType NoteProperty -Name 'MemberClass' -Value $row.MemberClass 155 | $r | Add-Member -MemberType NoteProperty -Name 'MemberName' -Value $row.MemberName 156 | $out += $r 157 | } 158 | 159 | $i++ 160 | $p = [int]($i * 100 / $l) 161 | # $elapsed = ((Get-Date) - $startTime).TotalSeconds 162 | # $remainingItems = $l - $i 163 | # $averageItemTime = $elapsed / $i 164 | Write-Progress "Evaluating $l roles and groups" ` 165 | -Status "$i evaluated" ` 166 | -PercentComplete $p 167 | # -SecondsRemaining ($remainingItems * $averageItemTime) 168 | } 169 | " 170 | 171 | 172 | " 173 | 174 | $f = Join-Path (Join-Path $env:USERPROFILE "Downloads") "RoleGroupMembership$CognosEnvironment.csv" 175 | $out | Export-Csv -Path $f -NoTypeInformation 176 | Start-Process -FilePath $f 177 | -------------------------------------------------------------------------------- /ContentStore/SpecBackup/README.md: -------------------------------------------------------------------------------- 1 | # Cognos Analytics 2 | 3 | # Backing up reports, dashboards, and data sets from Team Content/Reports 4 | 5 | ## Introduction 6 | Cognos stores the specifications for reports and data sets as XML and dashboards as JSON. It is possible to output the specs to the file system and sync them with a source control system like git. In my case, I manually cloned the repo, then wrote these scripts to do the routine work. 7 | 8 | I use Microsoft SQL Server and Microsoft Windows Server. Your mileage may vary. 9 | 10 | Hacking the Cognos Content Store database is not recommended. The correct, supported way to automate Cognos management tasks is by using the Cognos SDK. 11 | 12 | For supported version control, look for third-party tools like Motio CI. 13 | 14 | I used Windows Task Scheduler to make this run once per day. 15 | 16 | PowerShell can be used to run a query against the Content Store database and save the results to the file system. Git can help with version control so you can see changes over time and revert to the appropriate version of a report in case that's needed. HTMLTidy can clean up XML. This will make it easier to compare report versions. There are some prerequisites. 17 | 18 | 19 | ## Getting Started 20 | 1. Download and install Git for Windows. It should be at e:\install\Git-2.16.2-64-bit.exe. 21 | 1. Configure SSL for git. (see below) 22 | 1. Clone the repository that contains the report backups. It's currently at https://WSDOT@dev.azure.com/WSDOT/Business%20Intelligence%20and%20Reporting/_git/Cognos%20Reports. 23 | 1. Download HTMLTidy (tidy.exe at http://www.html-tidy.org/) into %USERPROFILE%\repos\WindowsTools. 24 | 1. Download and install these components of the Microsoft® SQL Server® 2014 Feature Pack: 25 | - ENU\x64\SQLSysClrTypes.msi (4,188 KB) 26 | - ENU\x64\SharedManagementObjects.msi (7,572 KB) 27 | - ENU\x64\PowerShellTools.msi (2,104 KB) 28 | 1. Create a task in the Windows Task Scheduler to run powershell -file "%USERPROFILE%\repos\ReportBackup\ReportBackup.ps1" once per day. 29 | ! TODO ! Hide the powershell window. 30 | 31 | ## Gotchas 32 | This document and the current state of the source code assume that things are stored in specific locations. 33 | - Repo containing this code: %USERPROFILE%\repos\ReportBackup 34 | - Repo containing the Cognos object specs: %USERPROFILE%\repos\CognosReports 35 | - Repo containing tidy.exe: %USERPROFILE%\repos\WindowsTools 36 | 37 | If these locations are not correct for your environment, track down all of the references in the code and fix them. 38 | 39 | 40 | 41 | ## Files ## 42 | 43 | ### ReportBackup.ps1 ### 44 | 45 | The wrapper. It pulls content from the git repo to ensure we're starting with current content, runs export.ps1 to get the specs from the Content Store, then runs push.ps1 to push the new content up to the remote repo. 46 | 47 | ### export.ps1 ### 48 | 49 | Exports the specs from the Content Store database to files on the local system. For performance reasons, the full content is captured only on Sundays. This enables git to record the deletion of content. On other days, only changes and additions in the last three days are output. 50 | 51 | ### push.ps1 ### 52 | 53 | Tidies the XML or JSON to make it easy to see differences between versions, then pushes the content to the remote repo. Uses HTML Tidy to tidy the XML files. 54 | 55 | ### tidy.exe ### 56 | Included here for convenience because I can. The license states, "Permission is hereby granted to use, copy, modify, and distribute this source code, or portions hereof, documentation and executables, for any purpose...".
You may want to be sure you have the current version (SourceForge or Github). 57 | -------------------------------------------------------------------------------- /ContentStore/SpecBackup/ReportBackup.ps1: -------------------------------------------------------------------------------- 1 | $exportResult = & ((Split-Path $MyInvocation.InvocationName) + "\export.ps1") 2 | if ($exportResult -eq 1) { 3 | #$fldr = ($env:USERPROFILE) + "\repos\CognosReports" 4 | $fldr = Join-Path ($env:USERPROFILE) "\repos\CognosReports" 5 | $msg = "`"Daily backup`"" 6 | & ((Split-Path $MyInvocation.InvocationName) + "\push.ps1") $fldr $msg 7 | } -------------------------------------------------------------------------------- /ContentStore/SpecBackup/export.ps1: -------------------------------------------------------------------------------- 1 | #$d = date 2 | #$dnum = $d.tostring("yyyyMMdd") 3 | $dlog = (date).tostring("yyyy-MM-dd HH:mm:ss.fff ") 4 | $dow = (date).DayofWeek.value__ 5 | $thisFolder = (Split-Path $MyInvocation.MyCommand.Source) 6 | $ReportBackupLog = $thisFolder + "\logs\ReportBackupLog.txt" 7 | $repo = "C:\Users\pulsed\repos\CognosReports" 8 | 9 | "$dlog Content Store export beginning" | Out-File -append $ReportBackupLog 10 | 11 | 12 | $sqlquery = "with src ( 13 | CMID, 14 | ObjectName, 15 | ObjectPath, 16 | ObjectClass, 17 | Modified) as 18 | ( 19 | select o.CMID 20 | , n.NAME 21 | , cast( 22 | replace( 23 | replace( 24 | replace( 25 | replace( 26 | replace( 27 | replace( 28 | replace( 29 | replace( 30 | replace( 31 | n.NAME, char(60), '' -- < 32 | ), char(62), '' -- > 33 | ), char(58), '' -- : 34 | ), char(34), '' -- quote 35 | ), char(47), '' -- / 36 | ), char(92), '' -- \ 37 | ), char(124), '' -- | 38 | ), char(63), '' -- ? 39 | ), char(42), '' -- * 40 | ) as varchar(max)) 41 | , cast(c.NAME as varchar(max)) 42 | , o.MODIFIED 43 | from CMOBJECTS o 44 | inner join CMOBJNAMES n on n.CMID = o.CMID 45 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 46 | where n.ISDEFAULT = 1 47 | and isdate(n.NAME) = 0 48 | and o.CMID = 2 49 | 50 | union all 51 | select o.CMID 52 | , n.NAME 53 | , cast(src.ObjectPath + '/' + 54 | replace( 55 | replace( 56 | replace( 57 | replace( 58 | replace( 59 | replace( 60 | replace( 61 | replace( 62 | replace( 63 | n.NAME, char(60), '' 64 | ), char(62), '' 65 | ), char(58), '' 66 | ), char(34), '' 67 | ), char(47), '' 68 | ), char(92), '' 69 | ), char(124), '' 70 | ), char(63), '' 71 | ), char(42), '' 72 | ) as varchar(max)) 73 | , cast(c.NAME as varchar(max)) 74 | , o.MODIFIED 75 | from CMOBJECTS o 76 | inner join CMOBJNAMES n on n.CMID = o.CMID 77 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 78 | inner join src on src.CMID = o.PCMID 79 | where n.ISDEFAULT = 1 80 | and n.CMID != 0 81 | ), 82 | obj as ( 83 | select CMID 84 | , REPLACE(s.ObjectPath,'/','\') + case when s.ObjectClass = 'exploration' then '.json' else '.xml' end as FilePath 85 | from src s 86 | where s.ObjectClass in ('report', 'exploration', 'dataSet2') 87 | and s.ObjectPath like 'Team Content/Reports%' 88 | ) 89 | 90 | select o.FilePath 91 | , s.SPEC as SPEC 92 | from obj o 93 | left join CMOBJPROPS7 s on s.CMID = o.CMID" 94 | 95 | ## If it's Sunday, don't filter the results. Get the entire Content Store. 96 | #if ($dow -ne 0) { 97 | #$sqlquery = $sqlquery + " 98 | # and c.Modified > dateadd(day, -3, getdate())" 99 | #} 100 | 101 | $sqlquery = $sqlquery + " 102 | order by 1" 103 | 104 | 105 | 106 | push-location 107 | $result = Invoke-Sqlcmd $sqlquery -ServerInstance "HQOLYMSQL19P" -Database "IBMCOGNOS" -MaxCharLength 1000000 108 | pop-location 109 | 110 | $l = $result.length 111 | 112 | if ($l -eq 0){ 113 | # No results? Something went wrong. Don't change anything. 114 | $dlog = (date).tostring("yyyy-MM-dd hh:mm:ss.fff ") 115 | "$dlog $l reports modified -- something went wrong" | Out-File -append $ReportBackupLog 116 | #"$dlog $sqlquery" | Out-File -append $ReportBackupLog 117 | return 0 118 | } 119 | 120 | 121 | $dlog = (date).tostring("yyyy-MM-dd hh:mm:ss.fff ") 122 | "$dlog $l reports modified" | Out-File -append $ReportBackupLog 123 | 124 | 125 | # If it's Sunday, delete everything under Team Content\Reports. 126 | # This is to delete items that are no longer in the Content Store. 127 | #if ($dow -eq 0) { 128 | $rpts = $repo + "\Team Content\Reports" 129 | Remove-Item -path $rpts -recurse 130 | #} 131 | 132 | 133 | # Write the results to the file system 134 | foreach($row in $result) { 135 | $filepath = $repo + "\" + $row.FilePath 136 | $contents = $row.SPEC 137 | if ($filepath.length -gt 240) { 138 | "The path is too long: $filepath" | Out-File -append $ReportBackupLog 139 | ##Try using 8.3 folder/file naming format 140 | #$folderpath = Split-Path $filepath 141 | #if (Test-Path $folderpath) { 142 | # #The folder exists 143 | # $filename = Split-Path $filepath -Leaf 144 | # $filepath = Join-Path (New-Object -ComObject Scripting.FileSystemObject).GetFolder($folderpath).shortpath $filename 145 | #} 146 | } 147 | 148 | #$fldr = Split-Path $filepath 149 | #if (!(Test-Path $fldr)) { 150 | # "Folder not found: $fldr" | Out-File -append $ReportBackupLog 151 | # "Folder not found: $fldr" 152 | #} 153 | 154 | try { 155 | if(!(Test-Path $filepath)) { 156 | try { 157 | New-Item $filepath -ItemType file -Force -Value $contents 158 | } 159 | catch { 160 | "Error: " + $row.FilePath | Out-File -append $ReportBackupLog 161 | " " + $_.Exception.Message | Out-File -append $ReportBackupLog 162 | #" " + $_.Exception.ItemName | Out-File -append $ReportBackupLog 163 | " " | Out-File -append $ReportBackupLog 164 | } 165 | } 166 | else { 167 | Set-Content -Path $filepath -Value $contents 168 | } 169 | } 170 | catch { 171 | "Error: " + $row.FilePath | Out-File -append $ReportBackupLog 172 | " " + $_.Exception.Message | Out-File -append $ReportBackupLog 173 | #" " + $_.Exception.ItemName | Out-File -append $ReportBackupLog 174 | " " | Out-File -append $ReportBackupLog 175 | } 176 | } 177 | 178 | $dlog = (date).tostring("yyyy-MM-dd HH:mm:ss.fff ") 179 | "$dlog Content Store export complete" | Out-File -append $ReportBackupLog 180 | 181 | return 1 182 | -------------------------------------------------------------------------------- /ContentStore/SpecBackup/push.ps1: -------------------------------------------------------------------------------- 1 | param([string]$fldr, [string]$msg) 2 | 3 | #cd $fldr 4 | 5 | # Identify all of the changes to reports. 6 | # Push the changes to the git repository. 7 | # Record in a text file what files changed. 8 | 9 | 10 | #$d = date 11 | $dnum = (date).tostring("yyyyMMdd") 12 | $dlog = (date).tostring("yyyy-MM-dd HH:mm:ss.fff ") 13 | $thisFolder = (Split-Path $MyInvocation.MyCommand.Source) 14 | $ReportBackupLog = $thisFolder + "\logs\ReportBackupLog.txt" 15 | $UpdatesLog = $thisFolder + "\logs\updates$dnum.txt" 16 | 17 | 18 | if ($fldr -eq "") { 19 | "$dlog no folder provided" | Out-File -append $ReportBackupLog 20 | exit 21 | } 22 | if (!(Test-Path "$fldr\.git" -PathType Container)) { 23 | # folder path not found 24 | "$dlog $fldr is not a git repository" | Out-File -append $ReportBackupLog 25 | exit 26 | } 27 | 28 | if ($msg -eq "") { 29 | "$dlog no message provided" | Out-File -append $ReportBackupLog 30 | exit 31 | } 32 | 33 | 34 | Set-Location -Path $fldr 35 | #Write-Host "Path set to $fldr" 36 | 37 | # get repo status 38 | $status = git status --porcelain 39 | 40 | # for each item that was changed (modified or added) 41 | # if it's an xml file, tidy the XML 42 | 43 | #Write-Host " " >> "..\updates$dnum.txt" 44 | $cmd = $env:USERPROFILE + "\repos\WindowsTools\tidy.exe" 45 | 46 | foreach ($line in $status) { 47 | if (($line.Substring(0, 3) -eq " M " -Or $line.Substring(0, 3) -eq " A ") -And $line.Substring($line.length - 5, 4) -eq ".xml") { 48 | # we want this one 49 | #$f = "`"" + $fldr + "\" + $line.Substring(4, $line.length - 5) + "`"" 50 | #$f = $f.replace("/", "\") 51 | $f = Join-Path $fldr $line.Substring(4, $line.Length - 5) 52 | 53 | if(!(Test-Path $f)) { 54 | "File not found: $f" | Out-File -append $ReportBackupLog 55 | } 56 | 57 | $args = @( 58 | "-q", 59 | "-xml", 60 | "-wrap", "0", 61 | "-indent", 62 | "-o", $f, 63 | $f 64 | ) 65 | 66 | # tidy 67 | #& "e:\tools\tidy.bat" $f 68 | #& "e:\tools\tidy.exe" "-q -xml -wrap 0 -indent -o $f $f" 69 | & $cmd $args 70 | 71 | ## record the change locally 72 | ##Write-Host $f 73 | #$f | Out-File -append $UpdatesLog 74 | } 75 | 76 | if (($line.Substring(0, 3) -eq " M " -Or $line.Substring(0, 3) -eq " A ") -And $line.Substring($line.length - 6, 5) -eq ".json") { 77 | # we want this one 78 | $f = "`"" + $fldr + "\" + $line.Substring(4, $line.length - 5) + "`"" 79 | $f = $f.replace("/", "\") 80 | 81 | (get-content $f) | convertfrom-json | convertto-json -depth 100 | set-content $f 82 | } 83 | } 84 | 85 | 86 | # now that we've tidied the xml, let's rerun status to see what really changed... 87 | $status = git status --porcelain 88 | # ...and record what changed 89 | foreach ($line in $status) { 90 | if (($line.Substring(0, 3) -eq " M " -Or $line.Substring(0, 3) -eq " A ") -And ($line.Substring($line.length - 5, 4) -eq ".xml" -Or $line.Substring($line.length - 6, 5) -eq ".json")) { 91 | # we want this one 92 | $f = "`"" + $fldr + "\" + $line.Substring(4, $line.length - 5) + "`"" 93 | $f = $f.replace("/", "\") 94 | 95 | # record the change locally 96 | #Write-Host $f 97 | $f | Out-File -append $UpdatesLog 98 | } 99 | } 100 | 101 | 102 | 103 | # push the changes to remote git repo 104 | git add -A 105 | git commit -m $msg 106 | git push 107 | 108 | $dlog = (date).tostring("yyyy-MM-dd HH:mm:ss.fff ") 109 | "$dlog git push complete" | Out-File -append $ReportBackupLog -------------------------------------------------------------------------------- /ContentStore/capabilities.sql: -------------------------------------------------------------------------------- 1 | use IBMCognos 2 | go 3 | ; 4 | declare @DirectoryNamespace varchar(128) = 'MyNamespaceName' 5 | ; 6 | with 7 | capability as ( 8 | select o.CMID 9 | 10 | from CMOBJECTS o 11 | inner join CMOBJNAMES n on n.CMID = o.CMID 12 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 13 | 14 | where n.ISDEFAULT = 1 15 | and n.NAME = 'Capability' 16 | and c.NAME = 'capability' 17 | ), 18 | capabilities as ( 19 | select cast(n.NAME as varchar(max)) as CapabilityPath 20 | , n.NAME 21 | , c.NAME as class 22 | , o.CMID 23 | , o.PCMID 24 | , o.DISABLED 25 | 26 | from CMOBJECTS o 27 | inner join CMOBJNAMES n on n.CMID = o.CMID 28 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 29 | --inner join capability cap on cap.CMID = o.PCMID 30 | 31 | where n.ISDEFAULT = 1 32 | and n.NAME = 'Capability' 33 | and c.NAME = 'capability' 34 | 35 | union all 36 | select cast(cap.CapabilityPath + '/' + n.NAME as varchar(max)) 37 | , n.NAME 38 | , c.NAME 39 | , o.CMID 40 | , o.PCMID 41 | , o.DISABLED 42 | from capabilities cap 43 | inner join CMOBJECTS o on o.PCMID = cap.CMID 44 | inner join CMOBJNAMES n on n.CMID = o.CMID 45 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 46 | 47 | where n.ISDEFAULT = 1 48 | ) 49 | 50 | select * 51 | into #capabilities 52 | from capabilities 53 | ; 54 | with 55 | capabilitypolicy as ( 56 | select c.CapabilityPath 57 | --, c.NAME 58 | --, c.class 59 | --, c.CMID 60 | --, c.PCMID 61 | , c.DISABLED 62 | , CONVERT(varchar(max), CONVERT(varbinary(max), p.POLICIES, 1), 2) as pol 63 | from #capabilities c 64 | inner join CMPOLICIES p on p.CMID = c.CMID 65 | ), 66 | cte ( 67 | CapabilityPath, 68 | pol, 69 | l, 70 | pos, 71 | curr, 72 | valout 73 | ) as ( 74 | -- Loop through the value 2 characters (1 hex value) at a time. 75 | -- Convert each value to ASCII. 76 | -- We'll replace anything small (non-printing characters) with LF to keep it simple. 77 | -- That may not be the best solution. 78 | select CapabilityPath 79 | , pol 80 | , len(pol) as l 81 | , 3 as pos 82 | , substring(pol, 1, 2) as curr 83 | , case 84 | when convert(int, convert(varbinary, '0x' + substring(pol, 1, 2), 1)) < 32 then char(10) 85 | else cast(cast(convert(binary(2), '0x' + substring(pol, 1, 2), 1) as char(1)) as varchar(max)) 86 | end as valout 87 | from capabilitypolicy 88 | union all 89 | select CapabilityPath 90 | , pol 91 | , l 92 | , pos + 2 as pos 93 | , substring(pol, pos, 2) as curr 94 | , valout + 95 | case 96 | when convert(int, convert(varbinary, '0x' + substring(pol, pos, 2), 1)) < 32 then char(10) 97 | else cast(cast(convert(binary(2), '0x' + substring(pol, pos, 2), 1) as char(1)) as varchar(max)) 98 | end as valout 99 | from cte 100 | where pos < l 101 | ), 102 | cte2 as ( 103 | -- Rank to identify the final value. 104 | select * 105 | , rank() over (partition by CapabilityPath order by pos desc) as rnk 106 | from cte 107 | ), 108 | a as ( 109 | -- We need only the results of the last step. 110 | select CapabilityPath 111 | , valout 112 | from cte2 113 | where rnk = 1 114 | ), 115 | q as ( 116 | select CapabilityPath 117 | , ROW_NUMBER() over (partition by CapabilityPath order by CapabilityPath) as rownum -- not reliable because string_split doesn't guarantee order until SQL 2022 118 | --, ROW_NUMBER() over (partition by CapabilityPath order by ordinal) as rownum -- Use with SQL 2022 or later 119 | , value as val 120 | --, substring(value, 11, 32) as val 121 | from a 122 | cross apply string_split(valout, char(10)) -- not reliable because string_split doesn't guarantee order until SQL 2022 123 | --cross apply string_split(valout, char(10), 1) -- Use with SQL 2022 or later 124 | ) 125 | 126 | -- Using a temporary table here reduces run time from 88 seconds to 8 seconds. 127 | select * 128 | into #q 129 | from q 130 | OPTION (MAXRECURSION 0) 131 | 132 | --select * 133 | --from #q 134 | --order by CapabilityPath 135 | ; 136 | 137 | with 138 | perms as ( 139 | select perm 140 | from ( 141 | values 142 | ('execute') 143 | , ('read') 144 | , ('setPolicy') 145 | , ('traverse') 146 | , ('write') 147 | ) v (perm) 148 | ), 149 | capabilityPerms as ( 150 | select q.CapabilityPath 151 | , q.rownum 152 | , n.NAME 153 | from #q q 154 | inner join CMOBJNAMES n on n.CMID = cast(SUBSTRING(val, 3, CHARINDEX(':', val, 3) - 3) as int) 155 | where q.val like '::%' 156 | and CHARINDEX(':', val, 3) > 0 157 | and n.ISDEFAULT = 1 158 | 159 | union 160 | select q.CapabilityPath 161 | , q.rownum 162 | , SUBSTRING(val, 3, 400) as 'Name' 163 | from #q q 164 | where q.val like '::%' 165 | and CHARINDEX(':', val, 3) = 0 166 | 167 | union 168 | select q.CapabilityPath 169 | , q.rownum 170 | , 'WSDOT\' + u.NAME 171 | from #q q 172 | inner join CMOBJNAMES n on n.NAME = q.val 173 | inner join cmobjprops33 u on u.CMID = n.CMID 174 | where n.NAME like @DirectoryNamespace + '%' 175 | 176 | union 177 | select q.CapabilityPath 178 | , q.rownum 179 | , p.perm 180 | from #q q 181 | inner join perms p on q.val like '%' + p.perm + '%' 182 | ), 183 | --capabilityPermType as ( 184 | -- select cp.CapabilityPath 185 | -- , cp.rownum 186 | -- , cp.NAME 187 | -- from capabilityPerms cp 188 | -- inner join perms p on p.perm = cp.NAME 189 | --), 190 | executeStart as ( 191 | select cp.CapabilityPath 192 | , cp.rownum 193 | , cp.NAME 194 | from capabilityPerms cp 195 | where cp.NAME = 'execute' 196 | ), 197 | readStart as ( 198 | select cp.CapabilityPath 199 | , cp.rownum 200 | , cp.NAME 201 | from capabilityPerms cp 202 | where cp.NAME = 'read' 203 | ), 204 | setPolicyStart as ( 205 | select cp.CapabilityPath 206 | , cp.rownum 207 | , cp.NAME 208 | from capabilityPerms cp 209 | where cp.NAME = 'setPolicy' 210 | ), 211 | traverseStart as ( 212 | select cp.CapabilityPath 213 | , cp.rownum 214 | , cp.NAME 215 | from capabilityPerms cp 216 | where cp.NAME = 'traverse' 217 | ), 218 | writeStart as ( 219 | select cp.CapabilityPath 220 | , cp.rownum 221 | , cp.NAME 222 | from capabilityPerms cp 223 | where cp.NAME = 'write' 224 | ), 225 | permClass as ( 226 | select cp.CapabilityPath 227 | , cp.rownum 228 | , cp.NAME 229 | , es.rownum as executeStart 230 | , rs.rownum as readStart 231 | , ss.rownum as setPolicyStart 232 | , ts.rownum as traverseStart 233 | , ws.rownum as writeStart 234 | from capabilityPerms cp 235 | left outer join executeStart es on es.CapabilityPath = cp.CapabilityPath 236 | left outer join readStart rs on rs.CapabilityPath = cp.CapabilityPath 237 | left outer join setPolicyStart ss on ss.CapabilityPath = cp.CapabilityPath 238 | left outer join traverseStart ts on ts.CapabilityPath = cp.CapabilityPath 239 | left outer join writeStart ws on ws.CapabilityPath = cp.CapabilityPath 240 | ) 241 | 242 | select c.CapabilityPath 243 | , case 244 | when pc.rownum between coalesce(pc.executeStart, 999) and coalesce(pc.readStart, pc.setPolicyStart, pc.traverseStart, pc.writeStart, 999) 245 | then 'execute' 246 | when pc.rownum between coalesce(pc.readStart, 999) and coalesce(pc.setPolicyStart, pc.traverseStart, pc.writeStart, 999) 247 | then 'read' 248 | when pc.rownum between coalesce(pc.setPolicyStart, 999) and coalesce(pc.traverseStart, pc.writeStart, 999) 249 | then 'setPolicy' 250 | when pc.rownum between coalesce(pc.traverseStart, 999) and coalesce(pc.writeStart, 999) 251 | then 'traverse' 252 | when pc.rownum between coalesce(pc.writeStart, 999) and 999 253 | then 'write' 254 | else 'inherited' 255 | end as permission 256 | , pc.NAME 257 | from #capabilities c 258 | left outer join permClass pc on pc.CapabilityPath = c.CapabilityPath 259 | and pc.NAME not in ( 260 | select perm 261 | from perms 262 | ) 263 | --and pc.NAME = 'BI Administrators' 264 | order by 1, 2, 3 265 | 266 | drop table #q 267 | drop table #capabilities 268 | -------------------------------------------------------------------------------- /ContentStore/udf_CognosPermissions.sql: -------------------------------------------------------------------------------- 1 | create function [dbo].[udf_CognosPermissions](@sIn varchar(max)) 2 | returns varchar(max) 3 | as 4 | begin 5 | declare @sBin varchar(max) = '' 6 | declare @sOut varchar(max) = '' 7 | declare @i int = 1 8 | declare @j int = 1 9 | declare @sTemp varchar(8) = '' 10 | declare @iByte int = 0 11 | declare @thisByte varchar(5) = '' 12 | 13 | declare @codes table ( 14 | letter char(1) COLLATE Latin1_General_CS_AS, 15 | number int 16 | ) 17 | 18 | insert @codes 19 | select 'A', 0 20 | union select 'B', 1 21 | union select 'C', 2 22 | union select 'D', 3 23 | union select 'E', 4 24 | union select 'F', 5 25 | union select 'G', 6 26 | union select 'H', 7 27 | union select 'I', 8 28 | union select 'J', 9 29 | union select 'K', 10 30 | union select 'L', 11 31 | union select 'M', 12 32 | union select 'N', 13 33 | union select 'O', 14 34 | union select 'P', 15 35 | union select 'Q', 16 36 | union select 'R', 17 37 | union select 'S', 18 38 | union select 'T', 19 39 | union select 'U', 20 40 | union select 'V', 21 41 | union select 'W', 22 42 | union select 'X', 23 43 | union select 'Y', 24 44 | union select 'Z', 25 45 | union select 'a', 26 46 | union select 'b', 27 47 | union select 'c', 28 48 | union select 'd', 29 49 | union select 'e', 30 50 | union select 'f', 31 51 | union select 'g', 32 52 | union select 'h', 33 53 | union select 'i', 34 54 | union select 'j', 35 55 | union select 'k', 36 56 | union select 'l', 37 57 | union select 'm', 38 58 | union select 'n', 39 59 | union select 'o', 40 60 | union select 'p', 41 61 | union select 'q', 42 62 | union select 'r', 43 63 | union select 's', 44 64 | union select 't', 45 65 | union select 'u', 46 66 | union select 'v', 47 67 | union select 'w', 48 68 | union select 'x', 49 69 | union select 'y', 50 70 | union select 'z', 51 71 | union select '0', 52 72 | union select '1', 53 73 | union select '2', 54 74 | union select '3', 55 75 | union select '4', 56 76 | union select '5', 57 77 | union select '6', 58 78 | union select '7', 59 79 | union select '8', 60 80 | union select '9', 61 81 | union select '+', 62 82 | union select '/', 63 83 | 84 | 85 | while @i < len(@sIn) 86 | begin 87 | set @sBin = @sBin + right('000000' + dbo.udf_ConvertFromBase10((select number from @codes where letter = substring(@sIn, @i, 1)), 2), 6) 88 | set @i = @i + 1 89 | end 90 | 91 | set @i = 1 92 | 93 | while @i < len(@sBin) 94 | begin 95 | set @sTemp = substring(@sBin, @i, 8) 96 | set @j = 1 97 | set @iByte = 0 98 | while @j <= 8 99 | begin 100 | set @iByte = @iByte + (cast(substring(@sTemp, @j, 1) as int) * (power(2, 8 - @j))) 101 | set @j = @j + 1 102 | end 103 | set @thisByte = case when @iByte = 0 then char(13) 104 | else char(@iByte) 105 | end 106 | set @sOut = @sOut + @thisByte 107 | set @i = @i + 8 108 | end 109 | 110 | return @sOut 111 | end 112 | GO 113 | -------------------------------------------------------------------------------- /ContentStore/udf_ConvertFromBase10.sql: -------------------------------------------------------------------------------- 1 | CREATE FUNCTION [dbo].[udf_ConvertFromBase10](@num INT, @base TINYINT) 2 | RETURNS VARCHAR(255) 3 | AS 4 | 5 | BEGIN 6 | -- Check for a null value. 7 | IF (@num IS NULL) 8 | RETURN NULL 9 | 10 | -- Declarations 11 | DECLARE @string VARCHAR(255) 12 | DECLARE @return VARCHAR(255) 13 | DECLARE @finished BIT 14 | DECLARE @div INT 15 | DECLARE @rem INT 16 | DECLARE @char CHAR(1) 17 | 18 | -- Initialize 19 | SELECT @string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' 20 | SELECT @return = CASE WHEN @num <= 0 THEN '0' ELSE '' END 21 | SELECT @finished = CASE WHEN @num <= 0 THEN 1 ELSE 0 END 22 | SELECT @base = CASE WHEN @base < 2 OR @base IS NULL THEN 2 WHEN @base > 36 THEN 36 ELSE @base END 23 | 24 | -- Loop 25 | WHILE @finished = 0 26 | BEGIN 27 | 28 | -- Do the math 29 | SELECT @div = @num / @base 30 | SELECT @rem = @num - (@div * @base) 31 | SELECT @char = SUBSTRING(@string, @rem + 1, 1) 32 | SELECT @return = @char + @return 33 | SELECT @num = @div 34 | 35 | -- Nothing left? 36 | IF @num = 0 SELECT @finished = 1 37 | 38 | END 39 | 40 | -- Done 41 | RETURN @return 42 | END 43 | GO 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023, 2024 doug pulse 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Maintenance/MaintenanceWindow/CognosMaintenance.ps1: -------------------------------------------------------------------------------- 1 | $logfile = "E:\logs\CognosMaintenance.txt" 2 | $datestring = (date).tostring("yyyy-MM-dd") 3 | $dlog = (date).tostring("yyyy-MM-dd hh:mm:ss.fff ") 4 | 5 | "$dlog Start Cognos maintenance" | Out-File -append $logfile 6 | 7 | # set the date to be sure this only happens once 8 | if ($datestring -eq "2020-02-02") { 9 | #Do something 10 | #Log as you go 11 | $msg = "" 12 | 13 | 14 | 15 | 16 | #Log final status 17 | $dlog = (date).tostring("yyyy-MM-dd hh:mm:ss.fff ") 18 | "$dlog Did something" | Out-File -append $logfile 19 | Send-MailMessage -To "email@domain.com" -From "email@domain.com" -Subject "$env:COMPUTERNAME Maintenance" -Body $msg -SmtpServer "server.domain.com" -Port 25 20 | } 21 | else { 22 | "$dlog Nothing to do" | Out-File -append $logfile 23 | Send-MailMessage -To "email@domain.com" -From "email@domain.com" -Subject "$env:COMPUTERNAME Maintenance" -SmtpServer "server.domain.com" -Port 25 24 | } 25 | 26 | 27 | $dlog = (date).tostring("yyyy-MM-dd hh:mm:ss.fff ") 28 | "$dlog End Cognos maintenance" | Out-File -append $logfile 29 | -------------------------------------------------------------------------------- /Maintenance/MaintenanceWindow/CognosStart.ps1: -------------------------------------------------------------------------------- 1 | $logfile = "E:\logs\CognosMaintenance.txt" 2 | $datestring = (date).tostring("yyyy-MM-dd") 3 | $dlog = (date).tostring("yyyy-MM-dd hh:mm:ss.fff ") 4 | 5 | "$dlog Starting Cognos Please wait 10 minutes for full service startup." | Out-File -append $logfile 6 | 7 | Start-Service -Name "IBM Cognos" 8 | 9 | $dlog = (date).tostring("yyyy-MM-dd hh:mm:ss.fff ") 10 | "$dlog End Cognos maintenance" | Out-File -append $logfile 11 | -------------------------------------------------------------------------------- /Maintenance/MaintenanceWindow/CognosStop.ps1: -------------------------------------------------------------------------------- 1 | $logfile = "E:\logs\CognosMaintenance.txt" 2 | $datestring = (date).tostring("yyyy-MM-dd") 3 | $dlog = (date).tostring("yyyy-MM-dd hh:mm:ss.fff ") 4 | 5 | "$dlog Start Cognos maintenance" | Out-File -append $logfile 6 | "$dlog Stopping Cognos" | Out-File -append $logfile 7 | 8 | Stop-Service -Name "IBM Cognos" 9 | -------------------------------------------------------------------------------- /Maintenance/MaintenanceWindow/README.md: -------------------------------------------------------------------------------- 1 | # Maintenance Window 2 | Most Cognos users expect it to be functional during regular business hours. But I work regular business hours. So how do I take Cognos down to perform maintenance tasks that can't be performed while Cognos is running? Or tasks that require me to restart the IBM Cognos service? 3 | 4 | Windows Task Scheduler to the rescue. 5 | Scheduling these three tasks to run daily or weekly outside of business hours meets the need. It can run every day, whether there is maintenance work or not. The maintenance script is configured to only perform actions on a specific day, so it will only happen once. Of course, you can customize it to run every day in a range of dates, or access a separate calendar to manage this. And if you schedule it weekly, an urgent need can be accommodated by scheduling a one-time run. 6 | 7 | 8 |
9 |
CognosStop.ps1
10 |
Stops the IBM Cognos service.
I schedule this for 1:30 a.m. Sundays.
11 | 12 |
CognosMaintenance.ps1
13 |
Performs custom maintanance actions.
I schedule this for 1:35 a.m. Sundays, providing enough time for the IBM Cognos service to stop before this script runs.
14 | 15 |
CognosStart.ps1
16 |
Starts the IBM Cognos service.
I schedule this for 3:05 a.m. Sundays. 90 minutes should be more than enough time to perform maintenance actions.
17 |
18 | -------------------------------------------------------------------------------- /Maintenance/SSL/README.md: -------------------------------------------------------------------------------- 1 | # SSL Cert Renewal 2 | SSL certificates expire. It's a little embarrassing when your Cognos service stops working because you missed a deadline. 3 | 4 | 5 |
6 |
SSLCertExpiration.csv
7 |
Contains data about your SSL cert expiration dates. Used by SSLExpiration.ps1
I have divided some of this data up by Cognos service (dispatcher, content manager, ...) but my systems are all single-server. Your mileage may vary.
8 | 9 |
SSLExpiration.ps1
10 |
Identifies any SSL certificates that will expire in the next 10 days. This is run daily using Windows Task Scheduler.
Calls RequestCognosServerCert.ps1 if appropriate.
11 | 12 |
RequestCongosServerCert.ps1
13 |
As a convenience, because my local webmaster is my Certificate Authority (CA), if the cert about to expire is a server cert, I generate the signing request and automatically email the request to the CA.
14 |
15 | -------------------------------------------------------------------------------- /Maintenance/SSL/RequestCognosServerCert.ps1: -------------------------------------------------------------------------------- 1 | param([string]$serverName, [string]$certType, [string]$expirationDate) 2 | 3 | $cognos = "E:\Program Files\ibm\cognos\analytics" 4 | 5 | e: 6 | cd "$cognos\bin" 7 | 8 | ThirdPartyCertificateTool.bat -java:local -c -e -d "CN=$serverName.domain.com,O=domain,C=US" -H $serverName.wsdot.loc -a RSA -r encryptRequest.csr -p NoPassWordSet 9 | 10 | $subject = "SSL Cert for $servername" 11 | $from = "DoNotReply@domain.com" 12 | # Assuming your webmaster provides your CA certs... 13 | $to = "Cognos Help ,Domain Webmaster " 14 | $attachment = ".\encrypt.csr" 15 | $body = "The $certType SSL cert for the Cognos service " 16 | $body += "on $serverName " 17 | $body += "will expire on $expirationDate.`r`n" 18 | $body += "Please provide the server cert in PEM (Base-64 encoded ASCII) format " 19 | $body += "for the attached signing request to Cognos Help ." 20 | 21 | Send-MailMessage -From $from -To $to -Subject $subject -Body $body -Attachments $attachment 22 | -------------------------------------------------------------------------------- /Maintenance/SSL/SSLCertExpiration.csv: -------------------------------------------------------------------------------- 1 | MachineName,MachineDescription,Type,Product,Expires 2 | CognosCMPrd,Cognos Production Content Manager,Root,Cognos Server,1/2/2050 3 | CognosDispPrd,Cognos Production Dispatcher,Root,Cognos Server,1/2/2050 4 | CognosTest,Cognos Test Server,Root,Cognos Server,1/2/2050 5 | CognosCMPrd,Cognos Production Content Manager,Intermediate,Cognos Server,1/2/2030 6 | CognosDispPrd,Cognos Production Dispatcher,Intermediate,Cognos Server,1/2/2030 7 | CognosTest,Cognos Test Server,Intermediate,Cognos Server,1/2/2030 8 | CognosCMPrd,Cognos Production Content Manager,Machine,Cognos Server,10/1/2022 9 | CognosDispPrd,Cognos Production Dispatcher,Machine,Cognos Server,10/1/2022 10 | CognosTest,Cognos Test Server,Machine,Cognos Server,11/1/2022 11 | CognosDispPrd,Cognos Production Gateway,Machine,IIS,10/1/2022 12 | CognosTest,Cognos Test Server,Machine,IIS,1/1/2022 13 | MyClientMachine,Joe's workstation,Machine,Framework Manager,1/20/2023 14 | MyClientMachine,Joe's workstation,Intermediate,Framework Manager,8/20/2034 15 | MyClientMachine,Joe's workstation,Root,Framework Manager,7/23/2054 16 | -------------------------------------------------------------------------------- /Maintenance/SSL/SSLExpiration.ps1: -------------------------------------------------------------------------------- 1 | # Store the cert expiration dates in a CSV file. 2 | $SSLInfo = Import-Csv -Path "E:\tools\SSLCertExpiration.csv" 3 | 4 | $SMTPServer = "server.domain.com" 5 | $from = "CognosServer " 6 | $to = "Cognos Help " 7 | $subject = "Cognos: An SSL cert is about to expire" 8 | 9 | # The email message can include a link to your documentation regarding your SSL certs. 10 | $wikiURL = "http://wiki.domain.com/wiki.php?id=cognos:admin:ssl_cert_schedules" 11 | 12 | foreach ($e in $SSLInfo) { 13 | $e.Expires=[Datetime]::ParseExact($e.Expires, 'M/d/yyyy', $null) 14 | if ((Get-Date) -gt $e.Expires.AddDays(-10)) { 15 | $certType = $e.Type # root, intermediate, or machine 16 | $certProduct = $e.Product # Cognos Analytics Server, Framework Manager, or IIS 17 | $certMachineName = $e.MachineName 18 | $certMachineDescription = $e.MachineDescription 19 | $certExpirationDate = $e.Expires 20 | 21 | $body = "The $certType SSL cert " 22 | $body += "for $certProduct " 23 | $body += "on $certMachineName ($certMachineDescription) " 24 | $body += "will expire on " + $certExpirationDate.ToString('MM/dd/yyyy') + ".`r`n" 25 | $body += "Please visit $wikiURL" 26 | 27 | Send-MailMessage -From $from -To $to -Subject $subject -Body $body 28 | if ($certProduct -eq "Cognos Server") { 29 | & ((Split-Path $MyInvocation.InvocationName) + "\RequestCognosServerCert.ps1") $certMachineName $certType $certExpirationDate.ToString('MM/dd/yyyy') 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IBM Cognos Analytics 2 | A bunch of mostly unrelated tools and code samples that may help the Cognos administrator, modeler, or report developer. 3 | 4 | **USE AT YOUR OWN RISK. MOST OF THE METHODS DEMONSTRATED HERE ARE NOT SUPPORTED BY IBM. THIS INFORMATION IS AT THIS LOCATION BECAUSE IT IS A CONVENIENT PLACE FOR ME TO STORE KNOWLEDGE I HAVE COMPILED REGARDING IBM COGNOS ANALYTICS. SOME OF THE CONTENT CONTAINED HEREIN MAY NOT WORK CORRECTLY OR MAY CAUSE PROBLEMS IN YOUR SYSTEM. EVEN THE ITEMS THAT I KNOW WORK FOR ME, MAY NOT WORK IN YOUR ENVIRONMENT.** 5 | 6 | See the README in each folder for details. 7 | -------------------------------------------------------------------------------- /RESTAPI/ModuleBusinessNames.ps1: -------------------------------------------------------------------------------- 1 | $ExistingVariables = Get-Variable | Select-Object -ExpandProperty Name 2 | 3 | $thisFolder = (Split-Path $MyInvocation.MyCommand.Source) 4 | Set-Location $thisFolder 5 | . ".\fn.ps1" 6 | 7 | 8 | function Get-TableMetadata { 9 | [cmdletbinding()] 10 | param ( 11 | [parameter(Mandatory=$true)] 12 | [string]$TableName, 13 | [parameter(Mandatory=$true)] 14 | [object]$TablesMetadata 15 | ) 16 | $matchCount = 0 17 | $r = [PSCustomObject]@{} 18 | foreach ($tm in $TablesMetadata) { 19 | if ($tm.TableName -eq $TableName) { 20 | $matchCount++ 21 | $r = $r | Select-Object -Property * -ExcludeProperty * 22 | $r | Add-Member -MemberType NoteProperty -Name 'Label' -Value $tm.Label 23 | $r | Add-Member -MemberType NoteProperty -Name 'Description' -Value $tm.Description 24 | } 25 | } 26 | 27 | if ($matchCount -gt 1) { 28 | "Warning: More than 1 record matches $Tablename. Returning last item found." 29 | } 30 | 31 | $r 32 | } 33 | 34 | function Get-ColumnMetadata { 35 | [cmdletbinding()] 36 | param ( 37 | [parameter(Mandatory=$true)] 38 | [string]$TableName, 39 | [parameter(Mandatory=$true)] 40 | [string]$ColumnName, 41 | [parameter(Mandatory=$true)] 42 | [object]$ColumnsMetadata 43 | ) 44 | $matchCount = 0 45 | $r = [PSCustomObject]@{} 46 | foreach ($cm in $ColumnsMetadata) { 47 | if ($cm.TableName -eq $TableName -and $cm.ColumnName -eq $ColumnName) { 48 | $matchCount++ 49 | $r = $r | Select-Object -Property * -ExcludeProperty * 50 | $r | Add-Member -MemberType NoteProperty -Name 'Label' -Value $cm.Label 51 | $r | Add-Member -MemberType NoteProperty -Name 'Description' -Value $cm.Description 52 | } 53 | } 54 | 55 | if ($matchCount -gt 1) { 56 | "Warning: More than 1 record matches $Tablename.$Columnname. Returning last item found." 57 | } 58 | 59 | $r 60 | } 61 | 62 | 63 | 64 | " 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------- 71 | starting 72 | -------------------------------------- 73 | " 74 | 75 | $protocol = "https" 76 | $serverName = "yourServerName" 77 | $port = "9300" 78 | $uriBase = "$protocol`://$serverName`:$port" 79 | $contentType = "application/json; charset=utf-8" 80 | 81 | $userNamespace = "yourDirectoryNamespace" 82 | $userName = Read-Host "User Name" 83 | $userPassword = "" 84 | $UserPwd = Read-Host "Password" -AsSecureString 85 | $userPassword = ConvertFrom-SecureString -SecureString $UserPwd -AsPlainText 86 | if (!$userPassword) { 87 | break 88 | } 89 | 90 | $modulePath = Read-Host "Module Path" 91 | $database = Read-Host "Database Name" 92 | $dbEnvironment = Read-Host "Database Environment" 93 | 94 | $sqlParams = @() 95 | $sqlParams += $database 96 | $sqlParams += $dbEnvironment 97 | 98 | " 99 | getting metadata..." 100 | # --------------------------------------------------------- 101 | # Data Library 102 | 103 | $sqlTable = "/* TABLE */ 104 | select 105 | EnvironmentName 106 | , HardwareSystemName 107 | , [DatabaseName] 108 | , TableName 109 | , coalesce(BusinessName, '') as BusinessName 110 | , coalesce([Description], '') as [Description] 111 | 112 | from [your database objects] 113 | 114 | where DatabaseMetadata.DatabaseName = ? 115 | and Environment.EnvironmentName = ? 116 | 117 | order by 1, 2, 3, 4 118 | ; 119 | " 120 | $DataCatalogDatabase = "yourDataCatalogDatabaseName" 121 | $DataCatalogServer = "yourDataCatalogServerName" 122 | $rsltTable = Invoke-Sql -datasource $DataCatalogServer -database $DataCatalogDatabase -sqlCommand $sqlTable -parameters $sqlParams 123 | $l = $rsltTable.length 124 | 125 | $tables = @() 126 | foreach($row in $rsltTable) { 127 | $r = [PSCustomObject]@{} 128 | $r | Add-Member -MemberType NoteProperty -Name 'TableName' -Value $row.TableName 129 | $r | Add-Member -MemberType NoteProperty -Name 'Label' -Value $row.BusinessName 130 | $r | Add-Member -MemberType NoteProperty -Name 'Description' -Value $row.Description 131 | $tables += $r 132 | } 133 | " 134 | got $l tables" 135 | if ($l -eq 0) { 136 | " Verify database name and environment." 137 | } 138 | 139 | $sqlColumn = "/* COLUMN */ 140 | select 141 | EnvironmentName 142 | , HardwareSystemName as ServerName 143 | , [DatabaseName] 144 | , TableName 145 | , [ColumnName] 146 | , coalesce(BusinessName, '') as BusinessName 147 | , coalesce([Description], '') as [Description] 148 | 149 | from [your database objects] 150 | 151 | where DatabaseMetadata.DatabaseName = ? 152 | and Environment.EnvironmentName = ? 153 | 154 | order by 1, 2, 3, 4, 5 155 | ; 156 | " 157 | $rsltTable = Invoke-Sql -datasource $DataCatalogServer -database $DataCatalogDatabase -sqlCommand $sqlColumn -parameters $sqlParams 158 | $l = $rsltColumn.length 159 | 160 | $columns = @() 161 | foreach($row in $rsltColumn) { 162 | $r = [PSCustomObject]@{} 163 | $r | Add-Member -MemberType NoteProperty -Name 'TableName' -Value $row.TableName 164 | $r | Add-Member -MemberType NoteProperty -Name 'ColumnName' -Value $row.ColumnName 165 | $r | Add-Member -MemberType NoteProperty -Name 'Label' -Value $row.BusinessName 166 | $r | Add-Member -MemberType NoteProperty -Name 'Description' -Value $row.Description 167 | $columns += $r 168 | } 169 | " 170 | got $l columns" 171 | if ($l -eq 0) { 172 | " Verify database name and environment." 173 | } 174 | 175 | 176 | 177 | " 178 | getting data module..." 179 | # --------------------------------------------------------- 180 | # Cognos REST API 181 | # docs at 182 | # http://:/api/api-docs 183 | 184 | 185 | $bdy = [PSCustomObject]@{} 186 | $paramarray = @() 187 | $param = [PSCustomObject]@{} 188 | $param | Add-Member -MemberType NoteProperty -Name 'name' -Value "CAMNamespace" 189 | $param | Add-Member -MemberType NoteProperty -Name 'value' -Value $userNamespace 190 | $paramarray += $param 191 | $param = [PSCustomObject]@{} 192 | $param | Add-Member -MemberType NoteProperty -Name 'name' -Value "CAMUsername" 193 | $param | Add-Member -MemberType NoteProperty -Name 'value' -Value $userName 194 | $paramarray += $param 195 | $param = [PSCustomObject]@{} 196 | $param | Add-Member -MemberType NoteProperty -Name 'name' -Value "CAMPassword" 197 | $param | Add-Member -MemberType NoteProperty -Name 'value' -Value $userPassword 198 | $paramarray += $param 199 | $bdy | Add-Member -MemberType NoteProperty -Name 'parameters' -Value $paramarray 200 | 201 | $body = ConvertTo-Json $bdy 202 | 203 | #" 204 | #/* log in */" 205 | $uri = "$uriBase/api/v1/session" 206 | $a = Invoke-RestMethod -Uri $uri -Method Put -contentType $contentType -SessionVariable "Session" -Body $body 207 | 208 | # " 209 | # #/* get session - fails but gets xsrf token */" 210 | # next line throws error, but retrieves a XSRF-Token cookie 211 | $a = Invoke-RestMethod -Uri $uri -Method Get -contentType $contentType -WebSession $Session -ErrorAction Ignore 212 | 213 | 214 | $Cookies = $Session.Cookies.GetCookies($uri) 215 | $XSRFTOKEN = $Cookies["XSRF-TOKEN"].Value 216 | 217 | $headers = @{ 218 | 'x-xsrf-token' = $XSRFTOKEN 219 | 'accept' = $contentType 220 | 'Cache-Control' = 'no-cache' 221 | } 222 | 223 | #" 224 | #/* get modules */" 225 | $uri = "$uriBase/api/v1/modules" 226 | $modules = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers -contentType $contentType -WebSession $Session 227 | $moduleId = "" 228 | 229 | foreach ($m in $modules.modules) { 230 | $path = Join-Path $($m.ancestors.name -join "\") $($m.name) 231 | $mpath = ($path).Replace("\", "/") 232 | if ($mpath -eq $modulePath) { 233 | $moduleId = $m.id 234 | } 235 | } 236 | 237 | if (!$moduleId) { 238 | " 239 | 240 | Module not found 241 | Verify module path and name." 242 | } 243 | else { 244 | #" 245 | #/* get the requested module */" 246 | $uri = "$uriBase/api/v1/modules/$moduleId" 247 | $module = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers -contentType $contentType -WebSession $Session 248 | 249 | #" 250 | #/* get the querySubject */" 251 | $qs = $module.querySubject 252 | 253 | foreach ($q in $qs) { 254 | #"===--- " + $q.identifier + " ---===" 255 | $tm = "" 256 | $tm = Get-TableMetadata -TableName $q.identifier -TablesMetadata $tables 257 | if ($tm.label) { 258 | "label = $($tm.label)" 259 | $q.label = $tm.label 260 | } 261 | if ($tm.Description) { 262 | if (!$q.description) { 263 | $q | Add-Member -MemberType NoteProperty -Name 'description' -Value $tm.Description 264 | } 265 | else { 266 | $q.Description = $tm.Description 267 | } 268 | } 269 | foreach ($qi in $q.item) { 270 | $cm = "" 271 | $cm = Get-ColumnMetadata -TableName $q.identifier -ColumnName $qi.queryItem.identifier -ColumnsMetadata $columns 272 | if ($cm.label) { 273 | $qi.queryItem.label = $cm.label 274 | } 275 | if ($cm.Description) { 276 | if (!$qi.queryItem.description) { 277 | $qi.queryItem | Add-Member -MemberType NoteProperty -Name 'description' -Value $cm.Description 278 | } 279 | else { 280 | $qi.queryItem.description = $cm.Description 281 | } 282 | } 283 | } } 284 | $newModule = $module | ConvertTo-Json -Depth 8 285 | 286 | #" 287 | #/* overwrite the requested module */" 288 | $module = Invoke-RestMethod -Uri $uri -Method Put -Headers $headers -contentType $contentType -WebSession $Session -Body $newModule 289 | } 290 | 291 | 292 | 293 | # log out 294 | $uri = "$uriBase/api/v1/session" 295 | $done = Invoke-RestMethod -Uri $uri -Method Delete -WebSession $Session 296 | $done 297 | 298 | 299 | 300 | $NewVariables = Get-Variable | Select-Object -ExpandProperty Name | Where-Object {$ExistingVariables -notcontains $_ -and $_ -ne "ExistingVariables"} 301 | if ($NewVariables) { 302 | #Write-Host "Removing the following variables:`n`n$NewVariables" 303 | Remove-Variable $NewVariables 304 | } 305 | else { 306 | #Write-Host "No new variables to remove!" 307 | } 308 | -------------------------------------------------------------------------------- /RESTAPI/README.md: -------------------------------------------------------------------------------- 1 | # Software REST API 2 | 3 | Swagger-based documentation: http://:/api/api-docs 4 | 5 | ## WARNING 6 | 7 | This code was developed to run on Windows 10, Window Server 2012 (or higher), PowerShell 7, SQL Server, Cognos Analytics 11.2.4, my environment, etc. Basically, your mileage may vary. 8 | 9 | ## Content 10 | 11 | #### fn.ps1 12 | 13 | A collection of functions useful for working with the Cognos Analytics REST API. 14 | 15 | #### ModuleBusinessNames.ps1 16 | 17 | Leverage your data catalog to automatically populate a data module with human-readable names and descriptions for tables (query subjects) and columns (query items). 18 | 19 | Assumes you are using Windows, PowerShell 7, SQL Server, Cognos Analytics 11.2.4, maybe other stuff. Basically, your mileage may vary. 20 | 21 | #### REST API Example.ps1 22 | 23 | An example showing how to leverage the common functions found in fn.ps1. 24 | 25 | Requires fn.ps1 26 | 27 | #### getCSV.ps1 28 | 29 | For one report, output all CSV outputs that are stored in Cognos. Requires the CSV output to already be saved in a report version. 30 | 31 | Requires fn.ps1 32 | 33 | -------------------------------------------------------------------------------- /RESTAPI/REST API Example.ps1: -------------------------------------------------------------------------------- 1 | # docs at 2 | # http://:/api/api-docs 3 | 4 | # $thisFolder = (Split-Path $MyInvocation.MyCommand.Source) 5 | # Set-Location $thisFolder 6 | # $functions = ".\fn.ps1" 7 | $functions = Join-Path $env:USERPROFILE "repos\CognosAdmin\RESTAPI\fn.ps1" 8 | . $functions 9 | 10 | $serverName = Read-Host "Cognos Server Name" 11 | 12 | $CognosSession = start-CognosSession -serverName $serverName 13 | 14 | if ($CognosSession) { 15 | $uriBase = $CognosSession.uriBase 16 | $protocol = $CognosSession.protocol 17 | $serverName = $CognosSession.serverName 18 | $port = $CognosSession.port 19 | $Session = $CognosSession.Session 20 | $headers = $CognosSession.Headers 21 | $contentType = $CognosSession.contentType 22 | #"******************** 23 | #Cognos Session:" 24 | #Write-Host $CognosSession 25 | #"********************" 26 | 27 | #===================================================================================================================== 28 | # DDDDD OOO SSS TTTTTTT U U FFFFFF FFFFFF 29 | # D D O O S T U U F F 30 | # D D O O SSS T U U FFFF FFFF 31 | # D D O O S T U U F F 32 | # DDDDD OOO SSS T UUUU F F 33 | #===================================================================================================================== 34 | 35 | " 36 | 37 | 38 | 39 | STARTING 40 | 41 | ======================================== 42 | " 43 | 44 | $contentId = "library" 45 | $uri = "$uriBase/api/v1/content/$contentId/items" 46 | $content = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers -contentType $contentType -WebSession $Session 47 | $content.content | Format-List 48 | 49 | #===================================================================================================================== 50 | # DDDDD OOO N N EEEEEE DDDDD OOO IIIII N N GGGG SSS TTTTTTT U U FFFFFF FFFFFF 51 | # D D O O N N N E D D O O I N N N G S T U U F F 52 | # D D O O N N N EEEE D D O O I N N N G GGG SSS T U U FFFF FFFF 53 | # D D O O N NN E D D O O I N NN G G S T U U F F 54 | # DDDDD OOO N N EEEEEE DDDDD OOO IIIII N N GGGG SSS T UUUU F F 55 | #===================================================================================================================== 56 | 57 | stop-CognosSession -CognosSession $CognosSession 58 | } -------------------------------------------------------------------------------- /RESTAPI/getCSV.ps1: -------------------------------------------------------------------------------- 1 | #$functions = Join-Path $env:USERPROFILE "repos\Cognos\RESTAPI\fn.ps1" 2 | Set-Location $thisFolder 3 | $functions = ".\fn.ps1" 4 | . $functions 5 | 6 | 7 | $serverName = Read-Host "Cognos server name" 8 | 9 | $CognosSession = start-CognosSession -serverName $serverName 10 | 11 | if ($CognosSession) { 12 | $uriBase = $CognosSession.uriBase 13 | # $protocol = $CognosSession.protocol 14 | # $serverName = $CognosSession.serverName 15 | # $port = $CognosSession.port 16 | $Session = $CognosSession.Session 17 | # $headers = $CognosSession.Headers 18 | # $contentType = $CognosSession.contentType 19 | 20 | #===================================================================================================================== 21 | # DDDDD OOO SSS TTTTTTT U U FFFFFF FFFFFF 22 | # D D O O S T U U F F 23 | # D D O O SSS T U U FFFF FFFF 24 | # D D O O S T U U F F 25 | # DDDDD OOO SSS T UUUU F F 26 | #===================================================================================================================== 27 | 28 | 29 | " 30 | 31 | 32 | 33 | 34 | 35 | " 36 | 37 | $path = Read-Host "Path to object" 38 | 39 | $href = get-CognosURIfromPath -path $path -CognosSession $CognosSession 40 | 41 | if ($href) { 42 | $co = get-CognosObjects -hrefItems "$href/items" -CognosSession $CognosSession -objectType "output" 43 | 44 | $b = @() 45 | foreach ($o in $co) { 46 | $b += $o.object.id 47 | } 48 | $storeID = "'$($b -join "','")'" 49 | 50 | # So we found the output. How do we get the CSV content? 51 | 52 | 53 | # There doesn't appear to be a way to do this using the REST API. 54 | # We'll run a query against the Content Store database to get the CSV results. 55 | 56 | $sql = " 57 | with 58 | objname as ( 59 | select o.CMID 60 | , coalesce(n2.name, n.NAME) as 'NAME' 61 | from CMOBJECTS o 62 | left outer join CMOBJNAMES n on n.CMID = o.CMID 63 | and n.LOCALEID = 92 -- en 64 | left outer join CMOBJNAMES n2 on n2.CMID = o.CMID 65 | and n2.LOCALEID = 118 -- en-us 66 | ), 67 | r as ( 68 | select convert(varchar(max), decompress(CONVERT(varbinary(max), d.DATAPROP, 1)), 2) as doc 69 | , 5 as pos 70 | from CMOBJECTS o 71 | inner join CMSTOREIDS s on s.CMID = o.CMID 72 | inner join objname n on n.CMID = o.CMID 73 | inner join CMCLASSES c on c.CLASSID = o.CLASSID 74 | inner join CMDATA d on d.CMID = o.CMID 75 | 76 | where d.CONTENTTYPE like 'application/csv%' 77 | and s.STOREID in ($storeID) 78 | ), 79 | cte ( 80 | doc 81 | , l 82 | , pos 83 | , curr 84 | , valout 85 | ) as ( 86 | -- Loop through the value 2 characters (1 hex value) at a time. 87 | -- Convert each value to ASCII. 88 | -- We'll replace anything small (non-printing characters) with LF to keep it simple. 89 | -- That may not be the best solution. 90 | select 91 | doc 92 | , len(doc) as l 93 | , pos + 2 as pos 94 | , substring(doc, pos, 2) as curr 95 | , case 96 | when convert(int, convert(binary(2), '0x' + substring(doc, pos, 2), 1)) = 9 then ',' 97 | when convert(int, convert(binary(2), '0x' + substring(doc, pos, 2), 1)) = 10 then char(10) 98 | when convert(int, convert(binary(2), '0x' + substring(doc, pos, 2), 1)) < 32 then '' 99 | else cast(cast( convert(binary(2), '0x' + substring(doc, pos, 2), 1) as char(1)) as varchar(max)) 100 | end as valout 101 | from r 102 | union all 103 | select 104 | doc 105 | , l 106 | , pos + 2 as pos 107 | , substring(doc, pos, 2) as curr 108 | , valout + 109 | case 110 | when convert(int, convert(binary(2), '0x' + substring(doc, pos, 2), 1)) = 9 then ',' 111 | when convert(int, convert(binary(2), '0x' + substring(doc, pos, 2), 1)) = 10 then char(10) 112 | when convert(int, convert(binary(2), '0x' + substring(doc, pos, 2), 1)) < 32 then '' 113 | else cast(cast( convert(binary(2), '0x' + substring(doc, pos, 2), 1) as char(1)) as varchar(max)) 114 | end as valout 115 | from cte 116 | where pos < l 117 | ), 118 | cte2 as ( 119 | -- Rank to identify the final value. 120 | select * 121 | , rank() over (partition by doc order by pos desc) as rnk 122 | from cte 123 | ) 124 | 125 | select cast(replace(valout, char(9), ',') as varchar(max)) as valout 126 | from cte2 127 | where rnk = 1 128 | OPTION (MAXRECURSION 0) 129 | " 130 | 131 | $DatabaseServer = Read-Host "Content Store database server name" 132 | $ContentStoreDB = Read-Host "Content Store database name" 133 | 134 | $dataset = Invoke-Sqlcmd $sql -ServerInstance $DatabaseServer -Database $ContentStoreDB -MaxCharLength 1000000 -ConnectionTimeout 30 -QueryTimeout 600 -TrustServerCertificate 135 | $l = $dataset.length 136 | #should be one row 137 | "$l rows found" 138 | 139 | $csv = @() 140 | foreach($row in $dataset) { 141 | $csv += $row.valout 142 | } 143 | 144 | $csv 145 | } 146 | else { 147 | "path not found" 148 | } 149 | 150 | 151 | #===================================================================================================================== 152 | # DDDDD OOO N N EEEEEE DDDDD OOO IIIII N N GGGG SSS TTTTTTT U U FFFFFF FFFFFF 153 | # D D O O N N N E D D O O I N N N G S T U U F F 154 | # D D O O N N N EEEE D D O O I N N N G GGG SSS T U U FFFF FFFF 155 | # D D O O N NN E D D O O I N NN G G S T U U F F 156 | # DDDDD OOO N N EEEEEE DDDDD OOO IIIII N N GGGG SSS T UUUU F F 157 | #===================================================================================================================== 158 | 159 | # log out 160 | $uri = "$uriBase/api/v1/session" 161 | $done = Invoke-RestMethod -Uri $uri -Method Delete -WebSession $Session 162 | } 163 | $done 164 | -------------------------------------------------------------------------------- /ReportSpecifications/README.md: -------------------------------------------------------------------------------- 1 | # ReportSpecifications 2 | Report samples for various purposes. These contain the report spec xml that can be easily imported into Cognos. If you get an error regarding version compatibility, just check the first line of your own report spec and update the version number in the sample to match your environment. 3 | 4 | 5 |
6 |
Scriptable Reports - Order of Methods
7 |
Demonstrates the order in which different events occur in a page module/custom control combination.
Uses OrderOfMethodsPageModule.js and OrderOfMethodsCustomControl.js.
8 | 9 |
Prompt Scripts
10 |
Demonstrates some ways to employ Prompts.js.
11 | 12 |
Parameter Value Automation
13 |
How to set a parameter value automatically and invisibly. One example of where this is helpful is to take advantage of database partitioning. For example, the database is partitioned by year, but the prompt page should not require year. A small, quick query can be employed to determine what years are involved based on the other parameter values, then the year or years passed to the main query to make it faster.
Uses Prompts.js and PromptAutoFinish.js
14 | 15 |
Parameter Reporter
16 |
Demonstrates how to use ParamDisplay.js, ParameterDisplay.js, and ParameterCapture.js.
17 | 18 |
Date Calculations
19 |
Demonstrates using MS SQL and Cognos Macros to compute various date values.
20 | 21 |
ToolTips
22 |
Show more detail about a data value in a tooltip.
23 | 24 |
VariableOperator
25 |
Ask the user how to filter.
26 | 27 |
Bursting
28 |
A very simple example of using the bursting feature.
29 | 30 |
CrosstabWithRowLabelHeaders
31 |
Use crosstab spaces to add headers to your row labels.
32 | 33 |
CommaDelimitedList
34 |
Use a repeater table to produce comma-delimited output.
35 | 36 |
ComplexLineChart
37 |
How to format a line chart with multiple dimensions.
38 |
39 | -------------------------------------------------------------------------------- /ReportSpecifications/Scriptable Reports - Order of Methods.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | { 15 | "ControlNum": "1" 16 | } 17 | 18 | 19 | { 20 | "ControlNum": "2" 21 | } 22 | 23 | 24 | { 25 | "ControlNum": "3" 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 46 | 47 | 52 | 53 | 54 | 55 | 60 | 61 | 62 | 63 | 68 | 69 | 70 | 75 | 76 | 77 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | No Data Available 97 | 98 | 101 | 102 | 103 | 104 | 105 | 106 | 112 | 113 | 114 | 115 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 184 | 185 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | Scriptable Reports - Order of Methods 200 | /content/folder[@name='Samples']/folder[@name='Models']/package[@name='GO Sales (query)']/model[@name='model'] 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | [Sales (query)].[Sales].[Quantity] 209 | 210 | 211 | 212 | 213 | 214 | 215 | [Sales (query)].[Branch].[City] 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | -------------------------------------------------------------------------------- /ReportSpecifications/ToolTips.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 18 | 19 | 20 | 21 | <style type="text/css"> 22 | 23 | a.tooltip{ 24 | position:relative; /*this is the key*/ 25 | z-index:24; text-decoration:none} 26 | 27 | a.tooltip:hover{z-index:25;} 28 | 29 | a.tooltip span{display: none} 30 | 31 | a.tooltip:hover span{ /*the span will display just on :hover state*/ 32 | display:block; 33 | position:absolute; 34 | top:2em; left:2em; width:14em; 35 | border:2px solid #000000; 36 | background-color:#ffffff; color:#000; 37 | } 38 | 39 | </style> 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | No Data Available 51 | 52 | 55 | 56 | 57 | 58 | 59 | 60 | 66 | 67 | 68 | 69 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 134 | 135 | 136 | 137 | HTML item 138 | 139 | 140 | 141 | 142 | 143 | 148 | 149 | 150 | 151 | 152 | '<a class="tooltip" href="#">' 153 | 154 | + 155 | (if ( [salesQuantity].[Quantity] > 10000000 ) then 156 | ('<font color ="Red">') 157 | else ('<font color ="Green">')) 158 | + 159 | 160 | 161 | '<font size="4.2em"><font style="Bold">&#x25a0;</font></font></font> 162 | 163 | <span class="classic"> 164 | 165 | <table border="0" width="100%" cellpadding="3" cellspacing="3" > 166 | <tr>' 167 | + 168 | (if ( [salesQuantity].[Quantity] > 10000000 ) then 169 | ('<td style ="background-color:Red"><font color="White"><font style="Bold"><font size="2.2em">&nbsp;' + [salesQuantity].[Product line] + '</font></font></font></td>') 170 | else ('<td style ="background-color:Green"><font color="White"><font style="Bold"><font size="2.2em">&nbsp;' + [salesQuantity].[Product line] + '</font></font></font></td>')) 171 | 172 | + 173 | 174 | '</tr> 175 | </table> 176 | 177 | <font size="2.2em">&nbsp;&nbsp; Quantity: </font>' + [salesQuantity].[strQuantity] + ' 178 | 179 | <br></br> 180 | 181 | </span></a>' 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | /content/folder[@name='Samples']/folder[@name='Models']/package[@name='GO Sales (query)']/model[@name='model'] 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | [Sales (query)].[Products].[Product line] 214 | 215 | 216 | 217 | 218 | 219 | 220 | [Sales (query)].[Sales].[Revenue] 221 | 222 | 223 | 224 | 225 | 226 | 227 | [Sales (query)].[Sales].[Quantity] 228 | 229 | 230 | 231 | 232 | 233 | 234 | cast ([Quantity], varchar(10)) 235 | 236 | 237 | 238 | 239 | ToolTips 240 | -------------------------------------------------------------------------------- /ReportSpecifications/VariableOperator.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | No Data Available 27 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | 42 | 43 | 44 | 45 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | City 131 | 132 | 133 | 134 | 135 | 136 | in 137 | 138 | 139 | starts with 140 | 141 | 142 | 143 | in 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 |
170 | 171 | 174 | 175 |
176 | 181 |
182 | 183 | 184 | 185 | 186 | 191 | 192 | 193 | 194 | 195 | 196 | 201 | 202 | 203 | 208 | 209 | 214 |
215 |
216 |
217 |
218 | 219 | 220 | 221 | 222 | 223 | /content/folder[@name='Samples']/folder[@name='Models']/package[@name='GO Sales (query)']/model[@name='model'] 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | [Sales (query)].[Branch].[City] 232 | 233 | 234 | 235 | 236 | 237 | 238 | [Sales (query)].[Sales].[Quantity] 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | [City] #prompt('Operator_City', 'token', 'in')# ?City? 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | if (ParamValue('Operator_City') is null) then ('in') else (ParamValue('Operator_City')) 256 | 257 | 258 | 259 | 260 | 261 | 262 |
-------------------------------------------------------------------------------- /SDK/README.md: -------------------------------------------------------------------------------- 1 | # Software Development Kit 2 | 3 | Cognos SDK Guide 4 | 5 |
6 |
7 |
8 |
9 | --------------------------------------------------------------------------------