Discussions
Categories
Groups
Community Home
Categories
INTERNAL ENABLEMENT
POPULAR
PUBLIC CLOUD
PRIVATE CLOUD
Quick Links
MY LINKS
HELPFUL TIPS
Back to website
Home
Intelligence (Analytics)
Custom ODA DataSet getting ResultSet columns by name not position
jaedabee
<p>Good morning,</p>
<p>
For a task I am working on we am trying to use a custom ODA Data Source and Data Set. The connections appear to be set up properly as we are able to generate results using our code. The issue we're having, though, is we would like to have the flexibility to reference columns in the <strong>ResultSet</strong> by their <strong>name </strong>and <span><em>not</em></span> by their <span>position</span>. After extensive debugging and a myriad of searches I'm still unable to avoid using the ResultSet column's position. This is likely something very simple that maybe I have missed because the documentation states that <strong>position</strong> is an <em>optional</em> property which is only used when the DataSet does not specify that it supports referencing ResultSet columns by name.<br><br>
So my question is: How do I specify that an ODA Data Set should <strong>use column names</strong> and <strong>not use position</strong>?<br><br>
Use case: We have queries that we're trying to reuse. While ideally the query would be modified to only return the columns needed there are cases where a query might return 3 columns and for a chart we only need 2 of those three columns: column #1 and column #3.<br><br>
Mitigation Strategy: We can manually provide information about which columns are provided by the query and programmatically update the position elements for the columns we care about. This is not ideal.<br><br>
Things we've tried:<br>
</p>
<ul class="bbc"><li>We are using Eclipse Mars 1 with BIRT 4.5</li>
<li>We're using the <strong>org.eclipse.datatools.connectivity.oda.dataSource extension</strong> point</li>
<li>In that extension we have specified a dataSource and a dataSet</li>
<li>Our dataSet has a number of dataTypeMappings.</li>
<li>We have a connection profile set up using the <strong>org.eclipse.datatools.connectivity.connectionProfile</strong> extension point</li>
<li>Our queries are provided in to the ODA Data Set using the <strong>queryText</strong> property.</li>
<li>We've tried use of cachedMetaData as well as removal of cachedMetaData from the dataSet in the Report Design file.</li>
<li>We've tried removal of the position property in the resultSet propery (which results in a NullPointerException because position cannot be null) as well as trying position = 0</li>
<li>name and nativeName properties are set in resultSet. nativeDataType is also set.</li>
<li>columnHints are set but not resultHints, is this an issue?</li>
<li>We've tried making our Query implementation extend both IQuery and IAdvancedQuery and tried using named Result Sets.</li>
</ul><br><p>Essentially I'm wondering if there's a property on the Data Set extension that maybe I missed, or if the internal PreparedStatement just doesn't use column names (only our ResultSet#getValue(int) methods are called, not ResultSet#getValue(String)), or if there's a property that sould be set on oda-data-set in the Report Design document to make it use column names and <strong>ignore</strong> the position attribute.<br><br>
Thank you very much for your time.</p>
<p> </p>
<p> </p>
<p> </p>
<p>(this is a copy and paste from the Eclipse BIRT forum where the question is currently unanswered, I hope that is Okay)</p>
Find more posts tagged with
Comments
jaedabee
<p>Hello. Here's some additional information from continued debugging:</p>
<p> </p>
<p>Package <strong>org.eclipse.birt.data.engine.odaconsumer</strong> has a ResultSet class with fetch() methods of integers only. I am guessing there's something that determines whether to use this one or a different ResultSet that has get...(string) methods?</p>
<pre class="_prettyXprint _lang-auto _linenums:0">
Thread [pool-4-thread-1] (Suspended (breakpoint at line 205 in ODAResultSet))
ODAResultSet.getDouble(int) line: 205
OdaResultSet.getDouble(int) line: 378
ResultSet.getDouble(int) line: 246
ResultSet.fetch() line: 174
OdiAdapter.fetch() line: 214
RowResultSet.fetch() line: 145
RowResultSet.doNext() line: 118
RowResultSet.next() line: 96
ExpandableRowResultSet.next() line: 63
SmartCacheHelper.populateData(IRowResultSet, IResultClass, SortSpec, long) line: 318
SmartCacheHelper.initInstance(CacheRequest, OdiAdapter, IResultClass) line: 285
SmartCacheHelper.initOdaResult(CacheRequest, OdiAdapter, IResultClass) line: 154
SmartCacheHelper.getResultSetCache(CacheRequest, ResultSet, IResultClass) line: 79
SmartCache.<init>(CacheRequest, ResultSet, IResultClass, DataEngineSession) line: 58
PassUtil.populateOdiResultSet(ResultSetPopulator, OdiResultSetWrapper, SortSpec) line: 99
PassUtil.pass(ResultSetPopulator, OdiResultSetWrapper, boolean) line: 62
PassManager.populateResultSetCacheInResultSetPopulator(OdiResultSetWrapper) line: 276
PassManager.populateDataSet(OdiResultSetWrapper) line: 238
PassManager.prepareDataSetResultSet(OdiResultSetWrapper) line: 98
PassManager.pass(OdiResultSetWrapper) line: 134
PassManager.populateResultSet(ResultSetPopulator, OdiResultSetWrapper, DataEngineSession) line: 74
ResultSetPopulator.populateResultSet(OdiResultSetWrapper) line: 218
CachedResultSet.<init>(BaseQuery, IResultClass, ResultSet, IEventHandler, DataEngineSession) line: 102
DataSourceQuery.execute(IEventHandler) line: 1067
PreparedOdaDSQuery$OdaDSQueryExecutor.executeOdiQuery(IEventHandler) line: 607
PreparedOdaDSQuery$OdaDSQueryExecutor(QueryExecutor).execute(IEventHandler) line: 1251
ServiceForQueryResults.executeQuery() line: 233
QueryResults.getResultIterator() line: 178
QueryResultSet.<init>(IDataEngine, ExecutionContext, IQueryDefinition, IQueryResults) line: 98
DteDataEngine.doExecuteQuery(IBaseResultSet, IQueryDefinition, Object, boolean) line: 168
DteDataEngine(AbstractDataEngine).execute(IBaseResultSet, IDataQueryDefinition, Object, boolean) line: 285
ExtendedGenerateExecutor.executeQueries() line: 205
ExtendedGenerateExecutor.execute() line: 65
ExtendedItemExecutor.execute() line: 62
SuppressDuplicateItemExecutor.execute() line: 43
LocalizedReportItemExecutor(WrappedReportItemExecutor).execute() line: 46
LocalizedReportItemExecutor.execute() line: 34
HTMLPageLM(HTMLBlockStackingLM).layoutNodes() line: 65
HTMLPageLM.layout() line: 92
HTMLReportLayoutEngine.layout(IReportExecutor, IReportContent, IContentEmitter, boolean) line: 100
RunAndRenderTask.doRun() line: 181
RunAndRenderTask.run() line: 77
ReportEditor.lambda$6(ToolBar, IRunAndRenderTask, InputStream) line: 590
234944546.run() line: not available
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1142
ThreadPoolExecutor$Worker.run() line: 617
Thread.run() line: 745</pre>
Clement Wong
<p>One of our Solutions Consultants, John Ward, wrote an article about <a data-ipb='nomediaparse' href='
http://www.ibm.com/developerworks/opensource/library/ba-birtextpoints/index.html#structure'>the
BIRT ODA extension point</a>. Have you seen it? And attached to the article is an reference example that you can use to compare your code to see if you've implemented the necessary methods.</p>
<p> </p>
<p>Or have you looked at the code behind the ODAs provided with OS BIRT such as the JDBC ODA (check out <a data-ipb='nomediaparse' href='
https://github.com/eclipse/birt/tree/c709c5b07db05398fd7f306201017650fa6bf438/data/org.eclipse.birt.report.data.oda.jdbc/src/org/eclipse/birt/report/data/oda/jdbc'>https://github.com/eclipse/birt/tree/c709c5b07db05398fd7f306201017650fa6bf438/data/org.eclipse.birt.report.data.oda.jdbc/src/org/eclipse/birt/report/data/oda/jdbc</a>for
example). </p>
jaedabee
<p>Hello Clement,</p>
<p> </p>
<p> First of all, thank you very much for your response. I had not seen that example. I did look at the code and compare it against ours and there are differences. It appears that the example is manually extracting data by getting the Report Document and using the Result set's Meta-Data as it is defined in the Report Document but overall the implementations are very close--we're simply wrapping a <strong>JDBC ResultSet</strong>. What I do not understand with that, though, is what is causing the <strong>DataSet </strong>to declare that it uses column names and not the position. To try and answer that one I did look at the second link. I have not yet been able to determine what causes the underlying ODA version of JDBC's PreparedStatement code to build a <strong>ResultSet </strong>wrapper delegate which can only use the column value ("<em>driverPosition</em>," I believe). There's something about an <strong>OdiAdapter </strong>(which does show up in the call stack) and a wrapper, but as of right now I'm still at a loss for what definitively says "don't use the driver position." I will keep looking.</p>
jaedabee
<p>An update:</p>
<p> </p>
<p> After looking more thoroughly into the attached example I did attempt to replicate creation of a Data Extraction Task within our result set. The issue here, however, is that the report document is located within a plug-in. To get around this I created a temporary file containing a copy of the report document. When attempting to read the file, however, I run into an exception opening the Report Document using the Extraction Task (the file does open and reading does occur, but it generates an EOFException deep in FileArchive). Passing the ReportEngine in to run the result task manually is certainly not an ideal solution. . . .</p>
<p> </p>
<p> In addition, I also took a very in-depth look at the sampledb project and the ODA-JDBC code, and a Development presentation on implementing custom drivers. I am not sure what it is, but I still cannot force the Data Set to ignore the position elements. I stumbled upon a driverBridge extension and thought that might be the way to go but JDBC doesn't show in our call stack at all.</p>
<p> </p>
<p>So at this point I'm completely at a loss. We'll have to work with the position property because I do not see any way to make the result set ignore position in our case and I am running short on time to investigate this. It is a solution but not very flexible.</p>
<p> </p>
<p>This is the exception stack for removing the position property from the resultSet property. Is there something that needs to be marked in the Report Design file to ignore it?</p>
<pre class="_prettyXprint _linenums:0">
Jan 21, 2016 8:27:58 PM org.eclipse.birt.report.engine.api.impl.EngineTask handleFatalExceptions
SEVERE: An error happened while running the report. Cause:
java.lang.NullPointerException
at org.eclipse.birt.report.data.adapter.internal.adapter.DataAdapterUtil.mergeHints(DataAdapterUtil.java:325)
at org.eclipse.birt.report.data.adapter.internal.adapter.DataAdapterUtil.adaptBaseDataSet(DataAdapterUtil.java:102)
at org.eclipse.birt.report.data.adapter.internal.adapter.OdaDataSetAdapter.<init>(OdaDataSetAdapter.java:55)
at org.eclipse.birt.report.data.adapter.impl.ModelAdapter.adaptDataSet(ModelAdapter.java:152)
at org.eclipse.birt.report.engine.adapter.ModelDteApiAdapter.doDefineDataSet(ModelDteApiAdapter.java:294)
at org.eclipse.birt.report.engine.adapter.ModelDteApiAdapter.defineDataSet(ModelDteApiAdapter.java:235)
at org.eclipse.birt.report.engine.data.dte.AbstractDataEngine.prepare(AbstractDataEngine.java:159)
at org.eclipse.birt.report.engine.executor.ReportExecutor.execute(ReportExecutor.java:122)
at org.eclipse.birt.report.engine.internal.executor.wrap.WrappedReportExecutor.execute(WrappedReportExecutor.java:60)
at org.eclipse.birt.report.engine.internal.executor.dup.SuppressDuplciateReportExecutor.execute(SuppressDuplciateReportExecutor.java:42)
at org.eclipse.birt.report.engine.internal.executor.wrap.WrappedReportExecutor.execute(WrappedReportExecutor.java:60)
at org.eclipse.birt.report.engine.internal.executor.l18n.LocalizedReportExecutor.execute(LocalizedReportExecutor.java:61)
at org.eclipse.birt.report.engine.api.impl.RunAndRenderTask.doRun(RunAndRenderTask.java:179)
at org.eclipse.birt.report.engine.api.impl.RunAndRenderTask.run(RunAndRenderTask.java:77)
at csf.analysis.rcp.editors.report.ReportEditor.lambda$6(ReportEditor.java:591)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)</pre>
<p>The exception occurs because position is null, and the underlying method takes a primitive int, causing an automatic exception. Setting position to 0 results in the column being marked invalid also.</p>