Main

Data Templates Archives

October 18, 2007

Data Dot Defined

After a weekend (there are 3 posts on this) spent in the mountains trudging, sorry 'hiking' up hill and down dale in freezing weather with no sleep I have finally caught the 'cold' that I knew was coming - with a head thats fit to burst I sound ridiculous and 'dalk dike dat, dall der dime' - good for 'd' aliteration fanatics but Im not one of them. There is a useful post coming for those of you using data templates.


If you have moved up to 10.1.3.3 and suddenly you're data template based reports are failing with:


Data not defined


Panic ye not - we have found the issue and its easily fixable. For some reason, we got strict with you in 10.1.3.3, if you had some parameter defined in your data template that you were not passing a value to via the user inteface. If you had a data template like the following, notice the P1 parameter:


<dataTemplate name="prodTemplate" dataSourceRef="demo-hr">
 <parameters>
  <parameter name="P1" dataType="character" defaultValue="Hello"/>
 </parameters>
 <dataQuery>
  <sqlStatement name="prodStmt">
   <![CDATA[
      select last_name, first_name, salary
      from employees
      where salary > 4000
      ]]>
  </sqlStatement>
 </dataQuery>
</dataTemplate>


But you had a report definition that lacked the P1 parameter definition, see the first image.







DT1:     DT2:

It would run in 10.1.3.2 but in 10.1.3.3 we would not let you and we would throw an error.
Until we fix it, to get around the problem either define the parameter in the report, see the second image or remove the parameter from the data template.

October 23, 2007

BLOB, CLOB, RAW and Looooong

The data engine introduced some new support for data types other than the normal varchar, date and number formats in 10.1.3.3. We now have support for the long, raw, clob and blob formats - and you do not have to do anything in the data template to handle these formats.
We auto detect for BLOBs and if it contains an image we will 'base64' encode it and drop that into the XML output so you can then render the image in the output.
If it has text we will return the
escaped format of the text and we only support UTF-8
encoded output. Other BLOB formats we leave alone.
There is an issue for CLOBs around a maximum size retrieved by a data template, that has been addressed in 10.1.3.3.1.

The above applies to 'data template' based reports. If you are using straight SQL things are a little more limited. We have BLOB and CLOB support and the auto detect for images is working but we do not have support for RAW and LONG column types at the moment - we're looking into that for a future release.

January 29, 2008

Data Template Building & Performance

I have been working with data templates for the last few daze ... we are doing some work on getting some performance numbers - at last. I have been building some more complex data templates than those I have built previously on the blog. The engine is extremely powerful and can do alot of the heavy lifting for you when it comes to grouping hierarchy and summary amounts.


Here's my latest.


<dataTemplate name="EMPLOYEES" defaultPackage="" dataSourceRef="demo-hr">
 <properties>
  <property name="include_parameters" value="true"/>
  <property name="include_null_Element" value="true"/>
  <property name="include_rowsettag" value="false"/>
  <property name="scalable_mode" value="off"/>
  <property name="db_fetch_size" value="300"/>
 </properties>
 <parameters/>
 <lexicals/>
 <dataQuery>
  <sqlStatement name="LOCATIONS" dataSourceRef="">
   <![CDATA[select  COUNTRIES.COUNTRY_NAME as COUNTRY,
  REGIONS.REGION_NAME as REGION,
  LOCATIONS.STREET_ADDRESS as STREET_ADDRESS,
  LOCATIONS.POSTAL_CODE as POSTAL_CODE,
  LOCATIONS.CITY as CITY,
  LOCATIONS.STATE_PROVINCE as STATE_PROVINCE,
         LOCATIONS.LOCATION_ID as LOCATION_ID1
 from  HR.LOCATIONS LOCATIONS,
  HR.COUNTRIES COUNTRIES,
  HR.REGIONS REGIONS
 where   COUNTRIES.REGION_ID=REGIONS.REGION_ID
 and  COUNTRIES.COUNTRY_ID=LOCATIONS.COUNTRY_ID]]>
  </sqlStatement>
  <sqlStatement name="DEPTS" dataSourceRef="">
   <![CDATA[select  DEPARTMENTS.DEPARTMENT_ID as DEPARTMENT_ID1,
  DEPARTMENTS.DEPARTMENT_NAME as DEPARTMENT_NAME
from  HR.DEPARTMENTS DEPARTMENTS
where   DEPARTMENTS.LOCATION_ID = :LOCATION_ID1]]>
  </sqlStatement>
  <sqlStatement name="EMPLOYEES" dataSourceRef="">
   <![CDATA[select     EMPLOYEES.EMPLOYEE_ID as EMPLOYEE_ID,
     EMPLOYEES.FIRST_NAME||' '||EMPLOYEES.LAST_NAME as EMP_NAME,
     EMPLOYEES.EMAIL as EMAIL,
     EMPLOYEES.PHONE_NUMBER as PHONE_NUMBER,
     EMPLOYEES.HIRE_DATE as HIRE_DATE,
     EMPLOYEES.SALARY as SALARY,
     EMPLOYEES.DEPARTMENT_ID as DEPT_ID,
     JOBS.JOB_TITLE as JOB_TITLE
 from     HR.JOBS JOBS,
     HR.EMPLOYEES EMPLOYEES
 where   EMPLOYEES.JOB_ID=JOBS.JOB_ID
 and department_id = :DEPARTMENT_ID1 ]]>
  </sqlStatement>
 </dataQuery>
 <dataStructure>
  <group name="G_REGION" source="LOCATIONS" groupFilter="">
   <element name="LOC_REGION" value="REGION" function=""/>
   <group name="G_LOC" source="LOCATIONS" groupFilter="">
    <element name="LOC_ADDR" value="STREET_ADDRESS" function=""/>
    <element name="LOC_CITY" value="CITY" function=""/>
    <element name="LOC_CODE" value="POSTAL_CODE" function=""/>
    <element name="LOC_STATE" value="STATE" function=""/>
    <element name="LOC_COUNTRY" value="COUNTRY" function=""/>
    <group name="G_DEPT" source="DEPTS" groupFilter="">
     <element name="DEPT_NUM" value="DEPARTMENT_ID1" function=""/>
     <element name="DEPT_NAME" value="DEPARTMENT_NAME" function=""/>
     <element name="DEPT_SALARY" value="G_EMP.SALARY" function="sum()"/>
     <element name="DEPT_COUNT" value="G_EMP.EMPLOYEE_ID" function="count()"/>
     <group name="G_JOB" source="EMPLOYEES" groupFilter="">
      <element name="JOB_TITLE" value="JOB_TITLE" function=""/>
      <group name="G_EMP" source="EMPLOYEES" groupFilter="">
       <element name="EMPNO" value="EMPLOYEE_ID" function=""/>
       <element name="EMP_NAME" value="EMP_NAME" function=""/>
       <element name="HIRE_DATE" value="HIRE_DATE" function=""/>
       <element name="PHONE_NUMBER" value="PHONE_NUMBER" function=""/>
       <element name="EMAIL" value="EMAIL" function=""/>
       <element name="SALARY" value="SALARY" function=""/>
      </group>
     </group>
    </group>
   </group>
  </group>
 </dataStructure>
</dataTemplate> 


Maybe not such a real data case but it shows off some of what you can do with the data engine. You can see I have 3 queries using bind variables LOCATIONS -> DEPARTMENTS -> EMPLOYEES. Now, rather than just then render the three levels in the grouping hierarchy I have created 5 levels:


G_REGION
    |
    |_ G_LOCATION
            |
            |_ G_DEPT
                     |      
                     |_ G_JOB
                              |
                              |_G_EMP

I have introduced the G_REGION and G_JOB levels into the data. Even thou we only have 3 levels in the queries the engine will calculate the hierarchies to be applied to the data.

The one drawback with the data templates is the fact that we do not have a builder for creating the templates. Good news on the way, I have been testing a new data template builder. This allows you to build your queries,


DTBuilder1:


set appropriate engine flags


DTBuilder2:


then bind them together into the grouping hierarchy


DTBuilder3:


and finally set properties for the individual columns.


DTBuilder4:


Its a nice tool - needs a little tweaking but its very close - of course usual disclaimers apply and it may look completely different by the time it hits the shelves. Look for it in a release coming soon ... performance numbers will come sooner.

July 8, 2008

Multiple DataSources I

Oh yeah, another one of those posts that will drag on over a couple of daze! This one comes out of some mail exchanges with one of our Oracle University trainers, Leta, who is revamping some of the class notes for Publisher. Leta has been working on the data template section for the EBS notes and found some holes in our doc! Shock, horror - yes, Leslie (our doc writer) is not infallible! Leslie assures me that the holes were left on purpose just to see if you folks out there are actually reading the documentation :0)
Leta was particularly looking at the XML data source we support in the data template. Its not badly written up in the documentation but there is some information missing and you have to connect the dots a bit. The saving grace is a full example later in the chapter - always useful for the light bulb moment when things click
Back to the point ... data templates can be used to access databases, multiple databases in fact - thats another post thou. Today its accessing XML datasources directly. Maybe you have a servlet that can serve up XML upon request or a static XML file that's dropped into a folder on a server periodically. Either way you can pull this data in via a data template. Yes, I know you can already do that by just calling it as a datasource in an Enterprise report. But what data templates bring to the table is the ability to merge your XML data with other XML data or with a sql based XML extract.
If you navigate to our documentation and look up the Data Templates section you'll find the somewhat incomplete section on XML data sources. To take the example given
<xml name="empxml" expressionPath=".//ROW[DEPTNO=$DEPTNO]"> <url method="GET" realm="" username="" password="">file:///d:/dttest/employee.xml</url> </xml>
This would be put under the dataQuery section alongside or instead of a sqlStatement if needed.
To explain the tags and attributes:
  • name - name given to this datasource and referenced in the grouping structure.
  • expressionPath - a means to link to an existing query. Assume the XML that will be generated from the file is:
      <?xml version="1.0" encoding="UTF-8" ?>
     <ROWSET>
      <ROW>
       <NAME>Donald OConnell</NAME> 
       <FIRST_NAME>Donald</FIRST_NAME>
       <LAST_NAME>OConnell</LAST_NAME>
       <SALARY>2600</SALARY>
       <ANNUAL_SALARY>31200</ANNUAL_SALARY>
       <FED_WITHHELD>8736</FED_WITHHELD>
       <JOB_TITLE>Shipping Clerk</JOB_TITLE>
       <DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
       <MANAGER>Kevin Mourgos</MANAGER>
      </ROW>
      <ROW>
       <NAME>Douglas Grant</NAME>
       <FIRST_NAME>Douglas</FIRST_NAME>
       <LAST_NAME>Grant</LAST_NAME>
       <SALARY>2600</SALARY>
       <ANNUAL_SALARY>31200</ANNUAL_SALARY>
       <FED_WITHHELD>8736</FED_WITHHELD>
       <JOB_TITLE>Shipping Clerk</JOB_TITLE>
       <DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
       <MANAGER>Kevin Mourgos</MANAGER> 
       </ROW>
     <ROWSET> 
    and I have a query
    select DEPTNO, DEPT_NAME
    from depts 
    I can use the expressionPath to link the two datasources
    .//ROW[DEPTNO=$DEPTNO] 
    is basically saying in SQL speak select * from empxml where .//ROW/DEPTNO = :DEPTNO -> from the sql query
  • url method - how should we retrieve the data with a POST or GET call
  • url realm - authentication name - this is seen when you log into an online resource sometimes. The popup will ask for your usr/pwd and will list the realm to be accessed.
  • url username - does the URL Im calling need a username passed
  • url password - does the URL Im calling need a password passed
  • url value - the url to access the XML e.g.file:///d:/dttest/employee.xml gets an XML file from the directory 'dttest' on the disk. http://tim.oracle.com/getXML calls a URL on a web server to fetch the data
There is an example of how this all hangs together in the doc, to save some effort here it is with some comments:
<?xml version="1.0"
encoding="WINDOWS-1252" ?>
<dataTemplate name="Employee Listing" description="List of Employees" version="1.0">
 <parameters> - Defines a single parameter for the Department Number - with default of 20:
   <parameter name="p_DEPTNO" dataType="character" defaultValue="20"/>
 </parameters>
 <dataQuery>
  <sqlStatement name="Q1">
   <![CDATA[SELECT DEPTNO,DNAME,LOC from dept order by
deptno]]>
  </sqlStatement>
  <xml name="empxml" expressionPath=".//ROW[DEPTNO=$DEPTNO]">-
Defines name - and link to DEPTNO in Q1
   <url method="GET" realm="" username="" password="">
     file:///d:/dttest/employee.xml</url> -
Defines url for xml data
   </xml>
  </dataQuery>-
 <dataStructure> - The following section specifies the
XML hierarchy for the returning data:
 <group name="G_DEPT" source="Q1"
  <element name="DEPT_NUMBER" value="DEPTNO" />
  <element name="DEPT_NAME" value="DNAME"/>
- This creates a summary total at the department level based
- on the salaries at the employee level for each department:
  <element name="DEPTSAL" value="G_EMP.SALARY"
function="SUM()"/>
  <element name="LOCATION" value="LOC" />
  <group name="G_EMP" source="empxml">
   <element name="EMPLOYEE_NUMBER" value="EMPNO" />
   <element name="NAME" value="ENAME"/>
   <element name="JOB" value="JOB" />
   <element name="MANAGER" value="MGR"/>
   <element name= "HIREDATE" value="HIREDATE"/>
   <element name="SALARY" value="SAL"/>
  </group>
 </group>
 </dataStructure>
</dataTemplate>
So, if you have the need to merge XML with SQL - now you know how to do it!

July 14, 2008

Lexical Reference Problems

Been in an interesting forum/email thread over the last few days with Naushad

I have a data template with a lexical parameter that is used in the SELECT caluse of the query.

DATA Template
<parameter name.............................../>
<parameter name="P_BREAK_COLUMN" dataType="varchar2"/>
<parameter name="P_BREAK" dataType="varchar2" defaultValue="gcc.segment3"/>
</parameters>
<lexicals>
</lexicals>
<dataQuery>
<sqlStatement name="Q_DATA">
<![CDATA[
SELECT &P_BREAK C_BREAK,
gcc.segment4 ,
exp.je_category ,
exp.vendor_number ,
exp.vendor_name ,
exp.invoice_number ,
exp.invoice_date ,
SUM (NVL (exp.accounted_dr, 0) - NVL (exp.accounted_cr, 0)) accounted_amt,
ffv4.description account_desc
FROM xxcus.XXGL_XGLOGEXP exp,
gl_code_combinations gcc,
fnd_flex_values_vl ffv4,
fnd_flex_value_sets ffs4
WHERE exp.code_combination_id = gcc.code_combination_id
AND ffs4.flex_value_set_id(+) = ffv4.flex_value_set_id
AND ffv4.flex_value(+) = gcc.segment4
AND ffs4.flex_value_set_name = 'ACCT_AFF'
GROUP BY &P_BREAK ,
gcc.segment4 ,
exp.je_category ,
exp.vendor_number ,
exp.vendor_name ,
exp.invoice_number ,
exp.invoice_date ,
ffv4.description
]]>
</sqlStatement>
</dataQuery>
<dataTrigger name="beforeReportTrigger" source="XXGL_XGLOGEXP_PKG.BeforeReport"/>
<dataStructure>
<group name="G_DATA" dataType="varchar2" source="Q_DATA">
<element name="C_BREAK" dataType="varchar2" value="C_BREAK"/>
<element name="SEGMENT4" dataType="varchar2" value="SEGMENT4"/>
<element name="JE_CATEGORY" dataType="varchar2" value="JE_CATEGORY"/>
...

The beforeReportTrigger looks like this:

FUNCTION BeforeReport RETURN BOOLEAN IS

BEGIN

IF P_BREAK_COLUMN = 'Location' THEN
P_BREAK := 'gcc.segment2';
ELSIF p_BREAK_COLUMN = 'Department' THEN
P_BREAK := 'gcc.segment3';
END IF;
fnd_file.put_line(fnd_file.log,'P_BREAK --> '||P_BREAK);

END;


The parameter starts with a default of "gcc.segment3". On execution of this report in EBS, the beforeReportTrigger fires and changes the value of P_BREAK to "gcc.segment2" (I can see that change in the concurrent reqs LOG file).

But when the SQL is executed, it still holds the default value. The fact that beforeReport has changed the value to segment2 is not visible to the SQL in the data XML template.

I have to admit I was fishing around for answer from development but Naushad continued to tinker with it and found the answer. Another gap in our doc we need to fill!

I found the source of my problem.
I have worked in Reports 9i for many years (since 1996 when it was version 4.5) and when I transition to XML data template seems like I have to unlearn some of that.

In Reports 9i, we define parameters in the “User Parameters” section. Those parameters can be assigned different values in the “before report” trigger. Essentially, we change the value of the parameter and the new values are visible to the SQL in the Data Model.

In XML data template, the parameters defined in the section are in a read only format. Any changes by the beforeReport trigger, to the variables in the parameter section are not visible to the SQL in the section.

I was able to resolve it by commenting out the declaration of parameter P_BREAK.

P_BREAK is defined as variable in the package spec and the beforeReport trigger changes the value as required.

<parameters>
 ……………………..
<!--  <parameter name="P_BREAK" dataType="varchar2" defaultValue="gcc.segment3"/>   -->
</parameters>  
<lexicals>
</lexicals>
<dataQuery>
 <sqlStatement name="Q_DATA">
  <![CDATA[
    SELECT &P_BREAK                C_BREAK,
    gcc.segment4            ,……
    FROM gl_code_combinations gcc, …..

The take away from the solution - the parameters in the data template are not updatable and you can declare public variables in your before report trigger and reference them inside the data template without the need to declare them.

June 10, 2009

Data Template Progression

I recently spent some time putting together a progression of data templates (DT) for a customer demo. Its a series of data templates that move you from the simple to the more complex, two query, before fetch trigger, group filter, summarizing all singing all dancing data template. I have heard requests this week for a three'er - looking at that. For now, satisfy yourselves with what I have.

Yep, still no builder but the 11g data builder is so cool it makes my geeky mouth water. Can not post images for fear of product management reprisal and bats up night dresses in the small hours (go Google it :0)
In spite of the lack of a DT builder I found it quite useful and so much faster to start off with the queries, get them working and returning data based on the parameters and to then move to the grouping, group filters (please dont use em) and summary columns. Rather than trying to write the whole this in one hit and then spend forever debugging.

During the demo we discussed the error messages and means to debug that BIP offers. Some of the layout errors are still mystifying at times '1=1' and '9<10' come to mind as true but very annoying error messages. You'll be pleased to here that turning on the debug for the data templates provides a mass of information about what is going on and of course what did not happen and why.

If you're interested you can get the progression here. Just unpack them under a directory under the BIP reports home directory. Fire up BIP and they will be available. They all run against the demo HR schema in an Oracle db. There is also a sql script for the supporting plsql package for the triggers.
Finally, just because its amusing and I wanted to share the mirth, check out this funny developer 'joke' from Bex on his blog, made me chortle!

July 8, 2009

German Data Template Nuggets

Another nugget of the gold stuff from Rainer, this time dynamic queries in data templates. Not an earth shattering discovery but its a nicely laid out walk through of how to add lexicals to your data template based queries using a before fetch trigger in the database. you can find the article here:

http://www.oracle.com/global/de/community/bip/tipps/dynamische_queries/index_en.html

for the German readers among you, you get it in your native tongue too

http://www.oracle.com/global/de/community/bip/tipps/dynamische_queries/index.html

If you're a newbie to the data template scene you might check out the Data Template Progression post and a few others in the data template archives.

August 28, 2009

Raw Data

Im seeing more and more folks wanting to render their stored XHTML in their outputs using BIP. I have written about the 'how' to render in the past but much more recently I have had customers that could not get to the rendering part because the extract was not extracting the XHTML in its raw format.

By raw I mean

'<p>This is a paragraph</p>'.

The data template engine under EBS 11i and R12 was escaping all the angle braces so the above string was coming out as

'& lt;p & gt;This is a paragraph& lt/;p& gt;',

ignore the spaces after the ampersand, just trying to stop the blogging platform from formatting them. Anyhoo, the sub template that converts the XHTML to XSL-FO was not working, its looking for '<p>' not '& lt;p& gt;'

Good news everyone, the dev team have implemented an enhancement for this so that you can get the raw data out. Still not quite out in the wild but look out for patch 8660920 if you are stuck.

All you need to do is change the dataType attribute for the CLOB column to 'xdo:xml' e.g.

<element name="ARTICLE_TEXT" dataType="xdo:xml" value="ARTICLE_TEXT"  />

A tiny tiny prize for the person that spotted the Futurama reference?

September 21, 2009

Multi Database Data Templates

In my post on Formatting Concatenated Datasources I mentioned the better way to do thangs was to use a data template to connect and execute queries on each databases and bring back a grouped/formatted data set.
So rather than the concatenated data set, thus

<DATA>
<SUPPLIERLIST>
 <G_VENDOR_NAME>
 <G_VENDOR_NAME>
</SUPPLIERLIST>
<PO_LIST>
 <G_PO>
 <G_PO>
 <G_PO>
 <G_PO>
 <G_PO>
 <G_PO>
</PO_LIST>
</DATA>

we use a data template to generate a hierarchical data set thus:

<DATA>
 <G_VENDOR>
 <G_PO>
 <G_PO>
 <G_PO>
 <G_VENDOR>
 <G_PO>
 <G_PO>
 <G_PO>
</DATA>

Remember, this is executing a query on SQLServer (or other db) to fetch the VENDOR data and executing another 'child' query on Oracle (or another db) to fetch the vendor's PO data.
This will allow you to simplify the layout template removing the need for the variables and the XPATH expression. It will also improve the performance immensely. With the concatenated data sources we were looping over the vendors. Setting a variable for the vendor and then looping over all of the POs filtering out the ones we did not want. So for every vendor we had to loop over every PO - its expensive.
With the data template approach we just following the data structures


<?for-each:G_VENDOR?>
...
<?for-each:G_PO?>
...
<?end for-each?>
<?end for-each?>

Much less expensive and simpler too and that satisfies the other mantra for layout templates, KISS!

How do you do it then?
Well first off you need to set up the oracle and SQL Server datasources. In 10.1.3.4 we ship the drivers for you for the popular non-Oracle dbs so setting them up is a relative cinch. We even provide a simple connection string for you to fill out.

MultiDT1.jpg

NB: if you are using SQL Server 2008, you can use the 2005 driver. Worked for me.

Once you have both data sources set up its then on to the data template. As I have mentioned previously, there is no 'builder' for data templates in 10.x releases. The world becomes a much nicer place with 11g but you'll have to wait a bit longer for that. If you are just starting out with data templates, check out the Data Template Progression entry to get started. Once you are comfortable with the format come back ...

You ready? Its not that tough to do, you just need to get the structure right. I fell in to a trap putting this example together (thanks Ahmed) but I can now share that with you. Here's the DT for the SQLServer (parent) and Oracle (child) queries and their structure.

<dataTemplate name="DATA" description="SQL Server - Oracle Extraction">
	<properties>
		<property name="include_parameters" value="true"/>
		<property name="include_null_Element" value="false"/>
		<property name="include_rowsettag" value="false"/>
		<property name="scalable_mode" value="off"/>
		<property name="debug_mode" value="on"/>
	</properties>
	<dataQuery>
		<sqlStatement name="VENDORS" dataSourceRef="locsqls"><![CDATA[
         select     VENDORS.VENDOR_ID as VENDOR_ID,
     VENDORS.VENDOR_ADDRESS as VENDOR_ADDRESS,
     VENDORS.VENDOR_NAME as VENDOR_NAME
         from     biptest.dbo.VENDORS VENDORS]]></sqlStatement>
		<sqlStatement name="POS" dataSourceRef="lorcl"><![CDATA[
           select po.PO_VENDOR as PO_VENDOR,
       po.PO_NUM as PO_NUM,
       po.PO_ITEM as PO_ITEM,
       po.PO_AMT as PO_AMT
           from     PO_TABLE po
       where po.po_vendor = :VENDOR_ID]]></sqlStatement>
	</dataQuery>
	<dataStructure>
		<group name="G_VENDOR" source="VENDORS">
			<element name="VENDOR_ID" value="VENDOR_ID"/>
			<element name="VENDOR_NAME" value="VENDOR_NAME"/>
			<element name="VENDOR_ADDRESS" value="VENDOR_ADDRESS"/>
			<group name="G_PO" source="POS">
				<element name="PO_NUM" value="PO_NUM"/>
				<element name="PO_ITEM" value="PO_ITEM"/>
				<element name="PO_AMT" value="PO_AMT"/>
			</group>
		</group>
	</dataStructure>
</dataTemplate>


I have emboldened the important parts where things deviate from a regular single db data template. Notice the dataSourceRef attributes on the sqlStatement element. These names need to match the ones you defined earlier.
Then the query link, notice Im using a bind variable (:VENDOR_ID). You can not use a link structure i.e.

<link name="SQLORCL_LINK" parentQuery="VENDORS" parentColumn="VENDOR_ID" childQuery="POS" childColumn="PO_VENDOR" condition="="/>

they are not supported. Something else of note, I did not hit it here but if you had VENDOR_ID on the SQLServer table and VENDOR_ID on the Oracle table you must ensure they have a different alias e.g. VENDOR_ID and VENDOR_ID1. Although they are on different dbs when it comes to linking them

where PO.VENDOR_ID = :VENDOR_ID

will at best confuse the heck out of the extraction engine and get unexpected results.

One other trap that I somehow fell into was to have each query under its own </dataQuery> element. they need to share one.

<dataQuery>
 <sqlStatement name="VENDORS" dataSourceRef="locsqls"><![CDATA[ SQL1 ]]>
 </sqlStatement>
 <sqlStatement name="POS" dataSourceRef="lorcl"><![CDATA[]]>
 </sqlStatement>
</dataQuery>

Otherwise you get weird table does not exist errors.

Once you have the data template in your report and valid you will get the data set back you want. You can then start adding the parameters, summary columns, etc you want.

<COMBINED>
<LIST_G_VENDOR>
<G_VENDOR>
<VENDOR_ID>1</VENDOR_ID>
<VENDOR_NAME>Nuts and Bolts Limited</VENDOR_NAME>
<VENDOR_ADDRESS>1 El Camino Real, Redwood City, CA 94065</VENDOR_ADDRESS>
<LIST_G_PO>
<G_PO>
<PO_NUM>123</PO_NUM>
<PO_ITEM>TV</PO_ITEM>
<PO_AMT>100</PO_AMT>
</G_PO>
<G_PO>
<PO_NUM>124</PO_NUM>
<PO_ITEM>Monitor</PO_ITEM>
<PO_AMT>300</PO_AMT>
</G_PO>
<G_PO>
<PO_NUM>125</PO_NUM>
<PO_ITEM>PC</PO_ITEM>
<PO_AMT>400</PO_AMT>
</G_PO>
</LIST_G_PO>
</G_VENDOR>
<G_VENDOR>
<VENDOR_ID>2</VENDOR_ID>
<VENDOR_NAME>Big Bike Motorsports</VENDOR_NAME>
<VENDOR_ADDRESS>10 Downing Street, London, SW1, UK</VENDOR_ADDRESS>
<LIST_G_PO>
<G_PO>
<PO_NUM>233</PO_NUM>
<PO_ITEM>TV</PO_ITEM>
<PO_AMT>1000</PO_AMT>
</G_PO>
<G_PO>
<PO_NUM>234</PO_NUM>
<PO_ITEM>Receiver</PO_ITEM>
<PO_AMT>340</PO_AMT>
</G_PO>
<G_PO>
<PO_NUM>235</PO_NUM>
<PO_ITEM>Phone</PO_ITEM>
<PO_AMT>150</PO_AMT>
</G_PO>
</LIST_G_PO>
</G_VENDOR>
</LIST_G_VENDOR>
</COMBINED>

Nice!

In terms of performance, its a much better way to get formatted/grouped data in your layout. But as I was discussing with someone this morning. Its a balancing act, you really want the dbs and the extraction engine to do the heavy lifting in terms of nesting structure, summary columns and sorting but you also want to provide the folks who build templates for users as much flexibility as possible.
Its not an exact science by any means, I always try and at least have the data engine extract using a 'sensible' hierarchy. Most if not all users are going to want to list invoices showing header information followed by the lines. Very rarely will they want to turn that hierarchy on its head, so its a good structure to have the DT extract plus the summary columns and sorting that go with it e.g invoice total, sort by line number, etc.

If you want to see the report file, you can get it here.

Happy Data Templating!

September 28, 2009

New BIP World Record

guinness.jpgI have seen some big reports in my time. There was the monster German Asset Summary report that I narrowly escaped having to maintain not long after I joined Oracle UK more than 11 years ago now. I say 'was', it got canned because it was bending Oracle Reports to do things it just did not want to do.

Alok beats all known contenders into a cocked hat, with his 'Annual Cotton Report', it contains, ready for this? 200 data templates, not just queries, data templates! It tips the scales at a meaty 3 Mb!

He was understandably having problems getting the report to load into the report builder. Hide from the development team to the rescue with a little javascript goodness. If you have a monster report and its not loading here's the tip.

You need to update XDOReportModel.TIMEOUTMSEC value in the javascript library XDOReportModel.js

You'll find it J2EE_HOME/applications/xmlpserver/xmlpserver/js/XDOReportModel.js

I got Alok's report to load by setting it thus:

XDOReportModel.TIMEOUTMSEC = 10000;

You will need to clear your browser cache to get the change picked up.

Please note, you are customizing at this point and Oracle Support, as fantastic as they are, can not help you if you screw up. Please back up the js library before you make any changes. Yep, it ought to be exposed as a parameter for the report builder but its not right now. I dont think the team ever imagined a 200 data template report.

A value of 10000 gives a 10 second time out but the report loads in about 7 seconds on my laptop.

If you have anything to challenge Alok's colossal cotton report or even a mini monster. Would love to hear about them. Not just in terms of queries but also in terms of size.

Guinness are currently ratifying Alok's mondo record report. I think I would need a pint or three of the black stuff after putting that together!

About Data Templates

This page contains an archive of all entries posted to Oracle BI Publisher Blog in the Data Templates category. They are listed from oldest to newest.

SQL is the next category.

Many more can be found on the main index page or by looking through the archives.

Top Tags

Powered by
Movable Type and Oracle