logo

7 сент. 2010 г.

BIEE: Переход между Direct Database Request с передачей параметров

Предположим, что вы столкнулись с необходимостью строить сложные запросы напрямую по источникам данных репозитория BIEE.
Причем не просто показывать единичный отчет, а отображать целую структуру отчетности. С переходами, drill-down'ом.

Приведу пример:
Создадим DDR, выводящий объем продаж по странам.

Далее создадим детализирующий DDR с объемом продаж по городам конкретной страны.


На столбце с показателем первого DDR укажем навигацию до детализирующего DDR.


Поместим 1-ый DDR на информационную панель


При нажатии на показатель какой-либо страны – переходим в детализирующий ансвер. Причем происходит фильтрация по стране.


Разберемся как этого достичь.


У меня в Firefox установлен HTTP-сниффер внутри firebug'а, который показывает следующий POST-запрос при навигации.


По сравнению с обычным поведением системы в таких случаях есть лишь одно отличие – наличие кода

setVariable="dashboard.variables['COUNTRY']"

именно этот код позволяет инициализировать конкретные презентационные переменные.

Добиться его появления можно так:
Найти файл viewhelper.js.


В нем немного подправить функцию (изменения выделены комментариями jack carver start/end).


//function NQNavigate(tForm, tNavInfo)
function NQNavigateHandler(tInfoBag, target)
{
NQWClearActiveMenu();

var tNavInfo = tInfoBag.oNavObject;
var bSWE = tNavInfo.sSWEView != null;

var nVals = Math.min(tNavInfo.vValues.length,10);

if (bSWE)
{
if (nVals > 0)
{
var sNavValue = "";
for(var i = 0 ; i != nVals ; ++i)
{
var tValue = tNavInfo.vValues[i];
if (tValue.sFormula == tNavInfo.sSWESrcFormula)
{
sNavValue = tValue.sValue;
break;
}
}

if (sNavValue != "")
{
//alert ("Debug Message: Calling NQSWENav('" + tNavInfo.sSWEView + "', '" + tNavInfo.sSWEApplet +
// "', '" + sNavValue + "');");
NQSWENav(tNavInfo.sSWEView, tNavInfo.sSWEApplet, sNavValue);
}
}
return;
}

var t = tNavInfo.vTargets[target];
t[0](t, tNavInfo);
var bPortal = tNavInfo.sPortal != null;
var tForm = GetGoForm(tNavInfo.sViewID,tNavInfo.sWindowTarget);

// alert(tNavInfo.sPortal);
// alert(tNavInfo.sPage);
// alert(tNavInfo.sPath);

var tExpr = XUICreateElement(saw.xml.kSawxNamespace, 'expr');

if (nVals > 0)
{
// Create the filter expression
tExpr.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
tExpr.setAttribute("xsi:type", "sawx:logical");
tExpr.setAttribute("op", "and");

for(var i = 0 ; i != nVals ; ++i)
{
var tValue = tNavInfo.vValues[i];

//tForm.elements['P' + (i*3 + 1)].value = tValue.sOp;
//tForm.elements['P' + (i*3 + 2)].value = tValue.sFormula;
//tForm.elements['P' + (i*3 + 3)].value = '1 ' + escapespaces(tValue.sValue);

var tFilterExpr = XUIAppendNewElement(tExpr, saw.xml.kSawxNamespace, 'expr');
XUISetXsiType(tFilterExpr, saw.xml.kSawxNamespace, "comparison");
XUISetAttributeString(tFilterExpr, "op", (null != tValue.sOp && tValue.sOp == 'null') ? "null" : "equal");


//jack carver start
if (tValue.sFormula.substr(0,1) == '.')
XUISetAttributeString(tFilterExpr, "setVariable",
"dashboard.variables['" + tValue.sFormula.substr(1) + "']");
//jack carver end

var tSQLExpr = XUIAppendNewElement(tFilterExpr, saw.xml.kSawxNamespace, 'expr');
XUISetXsiType(tSQLExpr, saw.xml.kSawxNamespace, "sqlExpression");
XUISetElementText(tSQLExpr, tValue.sFormula);

if (null == tValue.sOp || tValue.sOp != 'null')
{
var tValueExpr = XUIAppendNewElement(tFilterExpr, saw.xml.kSawxNamespace, 'expr');
XUISetXsiType(tValueExpr, saw.xml.kSawxNamespace, "untypedLiteral");
XUISetElementText(tValueExpr, tValue.sValue);
}
}

if (nVals == 1)
tExpr = tExpr.firstChild;
}

//adding updated viewstate
var tUpdatedViewStateDiv = document.getElementById("idViewStateDiv");

if(!(tForm == null || bPortal)) // must be a report with a go form
{
tForm.Action.value = 'Navigate';

tForm.Path.value = tNavInfo.sPath;

if (nVals > 0)
tForm.P0.value = saw.getXmlText(tExpr);
else
tForm.P0.value = "";
tForm.P1.value = "page";
tForm.P19.value = tNavInfo.sSearchID;
var sReportStatePath = tNavInfo.sViewID.substr(0,tNavInfo.sViewID.indexOf("~v:") == -1 ? tNavInfo.sViewID.length : tNavInfo.sViewID.indexOf("~v:"));
var tResultDiv = document.getElementById(sReportStatePath+"Result");
if (tResultDiv)
tForm.P18.value = tResultDiv.getAttribute("options").replace( new RegExp("s","gi"), "");

// Check if in compound layout view or view edit preview iframe
if ((typeof(CompoundViewEditor) != "undefined") || (typeof(TableViewEditor) != "undefined") || (typeof(PivotViewEditor) != "undefined") || (document.body.id == 'idViewPreview'))
{
tForm.target = "_blank";
tForm.ViewState.value = "";
}
else if (NQWIsInAnswers()) // lets stay in answers preview
{
tForm.action = GetViewForm().action;
}

if (tUpdatedViewStateDiv && tForm.ViewState)
tForm.ViewState.value = tUpdatedViewStateDiv.getAttribute("stateID");

// RIE: navigation needs
// to clear the view id so it doesn't go back into the same view
if (tForm.ViewID)
{
saw.addHiddenInput(tForm, "NavFromViewID", tForm.ViewID.value);
tForm.ViewID.value = "";
}
//added for nav to report so we know where we came from and can save that state
var sPageID = document.getElementById("idPageID");
if (sPageID)
saw.addHiddenInput(tForm, "PageID", sPageID.getAttribute("pageID"));

NQWSubmitFormWithView(tForm,tNavInfo.sViewID,null);
}
else // portal or no go form passed
{
var sURL = null;

tForm = document.forms["tempForm"];
if (!tForm)
tForm = saw.createForm("tempForm");

if(bPortal)
{
tForm.action = saw.commandToURL("Dashboard");
saw.addHiddenInput(tForm, "PortalPath", tNavInfo.sPortal);
saw.addHiddenInput(tForm, "P1", "dashboard");
if (tNavInfo.sPage)
saw.addHiddenInput(tForm, "Page", tNavInfo.sPage);
}
else if(tForm == null)
{
tForm.action = saw.commandToURL("Go");
saw.addHiddenInput(tForm, "Path", tNavInfo.sPath);
}

saw.addHiddenInput(tForm, "Action", "Navigate");

if (nVals > 0)
saw.addHiddenInput(tForm, "P0", saw.getXmlText(tExpr));
else
saw.addHiddenInput(tForm, "P0", "");
saw.addHiddenInput(tForm, "P19", tNavInfo.sSearchID);


if (tUpdatedViewStateDiv)
{
saw.addHiddenInput(tForm, "StateAction", "NewPage");
saw.addHiddenInput(tForm, "ViewState", tUpdatedViewStateDiv.getAttribute("stateID"));
}

// Check if in compound layout view or view edit preview iframe and open a new window
if ((typeof(CompoundViewEditor) != "undefined") || (typeof(TableViewEditor) != "undefined") || (typeof(PivotViewEditor) != "undefined") || (document.body.id == 'idViewPreview'))
{
tForm.target = "_blank";
}
else if (NQWIsInAnswers()) // replace parent - jump to portal
{
tForm.target = "_parent";
}
else
{
tForm.target = "_self";
}

// RIE: navigation needs
// to clear the view id so it doesn't go back into the same view
if (tForm.ViewID)
tForm.ViewID.value = "";

if (bPortal && parent && parent.getAnswersWorkspaceSyndicate)
{
var tSyn = parent.getAnswersWorkspaceSyndicate();
if (tSyn && tSyn.newWorkspaceModule(tForm.action + "&" + saw.convertFormToString(tForm)))
return;
}

NQWSubmitFormWithView(tForm,tNavInfo.sViewID,null);

}
}


Что важно, если вы используете переход из BI View, равного "Таблице", то будет инициализироваться переменная презентации с именем, равным альясу столбца в запросе DDR.

А если переход будет происходить из BI View, равного "Таблице среза", то инициализируется переменная презентации с именем, равным формуле (!) столбца.
Очевидно, что у DDR формул столбцов нет.

Поэтому придется немного схитрить. Открыть созданный DDR-запрос в CatalogManager'е и подправить его текст.


В примере задал формулу столбца ".COUNTRY" с точкой. Так как в javascript-файле мы вставляем условие

if (tValue.sFormula.substr(0,1) == '.')

тем самым не позволяем КАЖДОМУ столбцу любого запроса инициализировать переменную презентации.


П.С.
Что дополнительно нужно знать:
1) По умолчанию используется не больше 10 столбцов.
2) Не передаются значения столбцов-агрегатов (свойство aggRule не пустое).
3) Не передаются значения столбцов СПРАВА от столбца, вызвавшего переход.
4) Значения скрытых столбцов не передаются (обходной маневр через свойство "display:none")










Комментариев нет:

Отправить комментарий