Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 369486 - Cancel does not work for getResultSetMetaData()
Summary: Cancel does not work for getResultSetMetaData()
Status: RESOLVED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: BIRT (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 7
: P3 major (vote)
Target Milestone: 4.2.1   Edit
Assignee: pshi CLA
QA Contact: Xiaoying Gu CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-01-24 05:08 EST by ta CLA
Modified: 2012-08-21 02:14 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description ta CLA 2012-01-24 05:08:09 EST
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".
Comment 1 pshi CLA 2012-08-21 02:14:23 EDT
Fixed