| Summary: | Cancel does not work for getResultSetMetaData() | ||
|---|---|---|---|
| Product: | z_Archived | Reporter: | ta <tandree> |
| Component: | BIRT | Assignee: | pshi <pshi> |
| Status: | RESOLVED FIXED | QA Contact: | Xiaoying Gu <bluesoldier> |
| Severity: | major | ||
| Priority: | P3 | CC: | bluesoldier, tandree |
| Version: | unspecified | ||
| Target Milestone: | 4.2.1 | ||
| Hardware: | PC | ||
| OS: | Windows 7 | ||
| Whiteboard: | |||
Fixed |
Build Identifier: 3.7.2 RC1 Hello BIRT-Team, our company is using the BIRT framework as the main reporting engine bundled in our applications. Usually all our reports are based on OLAP datasources, for that reason we implemented our own ODA dataset and datasource drivers which connect to the Mondrian OLAP project. Currently we are adding cancel support of all our datasources and run into an implementation issue found in the BIRT framework. Let me explain our current problem: Problem: -------- Generally the ODA dataset flow is usally split into two queries, first: getResultSetMetaData() and second: getResultSet() The first one delivers informations about the columns of the resultset(names, types, etc.) and the second the rows of the resultset itself. I noticed that the cancel() method of a ODA dataset will only be invoked for the second getResultSet() query. Currently it is not possible to cancel the getResultSetMetaData() query. This works fine for SQL-Queries because getting the result set metadata is very fast and getting the resultset takes usually much longer. But due the nature of our OLAP systems getting the resultsset metadata can take very long. For that reason we need cancel support for the getResultSetMetaData() query. Solution: --------- I debugged the cancel support inside the BIRT framework and I think found a good solution. I used the BIRT 3.7.2-RC1 source. Please have a look inside the data engine project at: package: org.eclipse.birt.data.engine.executor class: DataSourceQuery method: prepare() line: 272 @SuppressWarnings("restriction") public IPreparedDSQuery prepare() throws DataException { if ( odaStatement != null ) throw new DataException( ResourceConstants.QUERY_HAS_PREPARED ); // create and populate a query specification for preparing a statement populateQuerySpecification(); odaStatement = dataSource.prepareStatement( queryText, queryType, this.querySpecificaton ); // Add custom properties to odaStatement addPropertiesToPreparedStatement( ); // Adds input and output parameter hints to odaStatement. // This step must be done before odaStatement.setColumnsProjection() // for some jdbc driver need to carry out a query execution before the metadata can be achieved // and only when the Parameters are successfully set the query execution can succeed. addParameterDefns(); IOdaDataSetDesign design = null; if( session.getDataSetCacheManager( ).getCurrentDataSetDesign( ) instanceof IOdaDataSetDesign ) design = (IOdaDataSetDesign)session.getDataSetCacheManager( ).getCurrentDataSetDesign( ); if ( design != null ) { if ( canAccessResultSetByName( design ) ) { // Ordering is important for the following operations. Column hints // should be defined // after custom fields are declared (since hints may be given to // those custom fields). // Column projection comes last because it needs hints and // custom // column information addCustomFields( design.getPrimaryResultSetName( ), odaStatement ); addColumnHints( design.getPrimaryResultSetName( ), odaStatement ); if ( this.projectedFields != null ) odaStatement.setColumnsProjection( design.getPrimaryResultSetName( ), this.projectedFields ); } else if( canAccessResultSetByNumber( design ) ) { addCustomFields( design.getPrimaryResultSetNumber( ), odaStatement ); addColumnHints( design.getPrimaryResultSetNumber( ), odaStatement ); if ( this.projectedFields != null ) odaStatement.setColumnsProjection( design.getPrimaryResultSetNumber( ), this.projectedFields ); } else { //NEW FIX STARTS HERE ICancellable queryCanceller = new OdaQueryCanceller( odaStatement, session.getStopSign() ); this.session.getCancelManager( ).register( queryCanceller ); prepareColumns( ); this.session.getCancelManager( ).deregister( queryCanceller ); //NEW FIX ENDS HERE } }else { //NEW FIX STARTS HERE ICancellable queryCanceller = new OdaQueryCanceller( odaStatement, session.getStopSign() ); this.session.getCancelManager( ).register( queryCanceller ); prepareColumns( ); this.session.getCancelManager( ).deregister( queryCanceller ); //NEW FIX ENDS HERE } //Here the "max rows" means the max number of rows that can fetch from data source. odaStatement.setMaxRows( this.getRowFetchLimit( ) ); // If ODA can provide result metadata, get it now try { ICancellable queryCanceller = new OdaQueryCanceller( odaStatement, session.getStopSign() ); this.session.getCancelManager( ).register( queryCanceller ); if( !session.getStopSign().isStopped() ) resultMetadata = getMetaData( (IOdaDataSetDesign)session.getDataSetCacheManager( ).getCurrentDataSetDesign( ), odaStatement ); if ( queryCanceller.collectException( ) != null ) { if ( !( queryCanceller.collectException( ).getCause( ) instanceof UnsupportedOperationException ) ) throw queryCanceller.collectException( ); } this.session.getCancelManager( ).deregister( queryCanceller ); } catch ( DataException e ) { // Assume metadata not available at prepare time; ignore the exception resultMetadata = null; } return this; } Description: ------------ Please refer to the //NEW FIX comments. As you can see I wrapped the prepareColumns() method with your queryCanceller pattern. That's all. We are currently using this fix and now our cancellation work fine in the getRestultSetMetaData() phase. It would be great if you could add this fix to the next BIRT 3.7.2 release. Reproducible: Always Steps to Reproduce: Please see "Details".