/*******************************************************************************
 * Copyright (c) 2004, 2005 Actuate Corporation. All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Eclipse Public License v1.0 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: Actuate Corporation - initial API and implementation
 ******************************************************************************/

package org.eclipse.birt.tests.data.engine.api;

import java.util.Collection;
import java.util.Iterator;

import org.eclipse.birt.core.data.DataType;
import org.eclipse.birt.data.engine.api.IBaseExpression;
import org.eclipse.birt.data.engine.api.IParameterMetaData;
import org.eclipse.birt.data.engine.api.IPreparedQuery;
import org.eclipse.birt.data.engine.api.IQueryResults;
import org.eclipse.birt.data.engine.api.IResultIterator;
import org.eclipse.birt.data.engine.api.IResultMetaData;
import org.eclipse.birt.data.engine.api.ISortDefinition;
import org.eclipse.birt.data.engine.api.querydefn.ConditionalExpression;
import org.eclipse.birt.data.engine.api.querydefn.FilterDefinition;
import org.eclipse.birt.data.engine.api.querydefn.GroupDefinition;
import org.eclipse.birt.data.engine.api.querydefn.OdaDataSetDesign;
import org.eclipse.birt.data.engine.api.querydefn.ParameterDefinition;
import org.eclipse.birt.data.engine.api.querydefn.QueryDefinition;
import org.eclipse.birt.data.engine.api.querydefn.ScriptExpression;
import org.eclipse.birt.data.engine.api.querydefn.SortDefinition;
import org.eclipse.birt.data.engine.core.DataException;

import testutil.APITestCase;
import testutil.ConfigText;

/**
 * DtE features test.
 */
public class FeaturesTest extends APITestCase
{
	
	/*
	 * @see org.eclipse.birt.data.engine.api.APITestCase#getDataSourceInfo()
	 */
	protected DataSourceInfo getDataSourceInfo( )
	{
		return new DataSourceInfo( ConfigText
				.getString( "Api.TestData.TableName" ), ConfigText
				.getString( "Api.TestData.TableSQL" ), ConfigText
				.getString( "Api.TestData.TestDataFileName" ) );
	}

	/**
	 * A standard report, test feature of: group, sort, filter.
	 */
	public void test1_group_sort_filter( ) throws Exception
	{
		String[] bindingNameGroup = new String[2];
		bindingNameGroup[0] = "GROUP_COUNTRY";
		bindingNameGroup[1] = "GROUP_CITY";
		
		IBaseExpression[] bindingExprGroup = new IBaseExpression[2];
		bindingExprGroup[0] = new ScriptExpression( "dataSetRow.COUNTRY" );
		bindingExprGroup[1] = new ScriptExpression( "dataSetRow.CITY" );
		
		GroupDefinition[] groupDefn = new GroupDefinition[]{
				new GroupDefinition( "group0"), new GroupDefinition( "group1")};
		groupDefn[0].setKeyExpression( "row.GROUP_COUNTRY" );
		groupDefn[1].setKeyExpression( "row.GROUP_CITY" );
		
		String[] bindingNameSort = new String[1];
		bindingNameSort[0] = "SORT_SALE_DATE";
		IBaseExpression[] bindingExprSort = new IBaseExpression[1];
		bindingExprSort[0] = new ScriptExpression( "dataSetRow.SALE_DATE" );

		SortDefinition[] sortDefn = new SortDefinition[]{new SortDefinition( )};
		sortDefn[0].setColumn( "SORT_SALE_DATE" );
		sortDefn[0].setSortDirection( ISortDefinition.SORT_DESC );

		
		
		String[] bindingNameFilter = new String[1];
		bindingNameFilter[0] = "FILTER_AMOUNT";
		IBaseExpression[] bindingExprFilter = new IBaseExpression[1];
		bindingExprFilter[0] = new ScriptExpression( "dataSetRow.AMOUNT" );
		FilterDefinition[] filters = new FilterDefinition[]{new FilterDefinition(
				new ScriptExpression( "row.FILTER_AMOUNT > 100" ) )};
		
		String[] bindingNameRow = new String[6];
		bindingNameRow[0] = "ROW_0";
		bindingNameRow[1] = "ROW_rowPosition";
		bindingNameRow[2] = "ROW_COUNTRY";
		bindingNameRow[3] = "ROW_CITY";
		bindingNameRow[4] = "ROW_SALE_DATE";
		bindingNameRow[5] = "ROW_AMOUNT";
		IBaseExpression[] bindingExprRow = new IBaseExpression[6];
		bindingExprRow[0] = new ScriptExpression( "dataSetRow[0]" );
		bindingExprRow[1] = new ScriptExpression( "dataSetRow._rowPosition" );
		bindingExprRow[2] = new ScriptExpression( "dataSetRow.COUNTRY" );
		bindingExprRow[3] = new ScriptExpression( "dataSetRow.CITY" );
		bindingExprRow[4] = new ScriptExpression( "dataSetRow.SALE_DATE" );
		bindingExprRow[5] = new ScriptExpression( "dataSetRow.AMOUNT" );

		createAndRunQuery( bindingNameGroup,
				bindingExprGroup,
				groupDefn,
				bindingNameSort,
				bindingExprSort,
				sortDefn,
				bindingNameFilter,
				bindingExprFilter,
				filters,
				bindingNameRow,
				bindingExprRow );
		checkOutputFile( );
	}

	/**
	 * Test feature of group.
	 */
	public void test2_FeatureofGroup( ) throws Exception
	{
		String[] bindingNameGroup = new String[2];
		bindingNameGroup[0] = "GROUP_COUNTRY";
		bindingNameGroup[1] = "GROUP_CITY";
		
		IBaseExpression[] bindingExprGroup = new IBaseExpression[]{
				new ScriptExpression( "dataSetRow.COUNTRY", 0 ),
				new ScriptExpression( "dataSetRow.CITY", 0 ),
				};
		
		
		GroupDefinition[] groupDefn = new GroupDefinition[]{
				new GroupDefinition( ), new GroupDefinition( )};
		groupDefn[0].setKeyExpression( "row.GROUP_COUNTRY"  );
		groupDefn[1].setKeyExpression( "row.GROUP_CITY" );

		String[] bindingNameRow = new String[4];		
		bindingNameRow[0] = "ROW_COUNTRY";
		bindingNameRow[1] = "ROW_CITY";
		bindingNameRow[2] = "ROW_SALE_DATE";
		bindingNameRow[3] = "ROW_AMOUNT";
		
		IBaseExpression[] bindingExprRow = new IBaseExpression[]{
				new ScriptExpression("dataSetRow.COUNTRY"),
				new ScriptExpression("dataSetRow.CITY"),
				new ScriptExpression( "dataSetRow.SALE_DATE" ),
				new ScriptExpression( "dataSetRow.AMOUNT" )
		};
		
		createAndRunQuery( bindingNameGroup,
				bindingExprGroup,
				groupDefn,
				null,
				null,
				null,
				null,
				null,
				null,
				bindingNameRow,
				bindingExprRow );
		checkOutputFile( );
	}

	/**
	 * Test feature of incorrect sort key, throw exception
	 */
	public void test3_IncorrectSortKey( ) throws Exception
	{
		String[] bindingNameGroup = new String[2];
		bindingNameGroup[0] = "GROUP_COUNTRY";
		bindingNameGroup[1] = "GROUP_CITY";
		
		IBaseExpression[] bindingGrpEpre = new IBaseExpression[]{
				
		        new ScriptExpression("dataSetRow.COUNTRY"), 
		        new ScriptExpression("dataSetRow.CITY")};
		
		GroupDefinition[] groupDefn = new GroupDefinition[]{
				new GroupDefinition("group0" ), new GroupDefinition( "group1")};
		groupDefn[0].setKeyExpression( "row.COUNTRY" );
		groupDefn[1].setKeyExpression( "row.CITY" );
		

		String[] bindingNameSort = new String[]{
				"SALE_SORT"
		};
		
		IBaseExpression[] bindingExprSort = new IBaseExpression[]{
				new ScriptExpression( "dataSetRow.SALE_DATE" )
		};
		SortDefinition[] sortDefn = new SortDefinition[]{new SortDefinition( )};
		sortDefn[0].setColumn( "SALE_DA" );
		sortDefn[0].setSortDirection( ISortDefinition.SORT_ASC );
		
		String[] bindingNameRow = new String[4];		
		bindingNameRow[0] = "ROW_COUNTRY";
		bindingNameRow[1] = "ROW_CITY";
		bindingNameRow[2] = "ROW_SALE_DATE";
		bindingNameRow[3] = "ROW_AMOUNT";
		IBaseExpression[] bindingExprRow = new IBaseExpression[4];
		bindingExprRow[0] = new ScriptExpression( "dataSetRow.COUNTRY" );
		bindingExprRow[1] = new ScriptExpression( "dataSetRow.CITY" );
		bindingExprRow[2] = new ScriptExpression( "dataSetRow.SALE_DATE" );
		bindingExprRow[3] = new ScriptExpression( "dataSetRow.AMOUNT" );

		
		try
		{
			createAndRunQuery( bindingNameGroup,
					bindingGrpEpre,
					groupDefn,
					bindingNameSort,
					bindingExprSort,
					sortDefn,
					null,
					null,
					null,
					bindingNameRow,
					bindingExprRow );
			fail( "Should throw DteException!" );
		}
		catch ( DataException e )
		{
			// TODO: verify e has expected error code
		}
	}

	/**
	 * Test feature without any group, sort, filter
	 */
	public void test4_without_group_sort_filter( ) throws Exception
	{
		String[] bindingNameRow = new String[4];		
		bindingNameRow[0] = "ROW_COUNTRY";
		bindingNameRow[1] = "ROW_CITY";
		bindingNameRow[2] = "ROW_SALE_DATE";
		bindingNameRow[3] = "ROW_AMOUNT";
		IBaseExpression[] bindingExprRow = new IBaseExpression[4];
		bindingExprRow[0] = new ScriptExpression( "dataSetRow.COUNTRY" );
		bindingExprRow[1] = new ScriptExpression( "dataSetRow.CITY" );
		bindingExprRow[2] = new ScriptExpression( "dataSetRow.SALE_DATE" );
		bindingExprRow[3] = new ScriptExpression( "dataSetRow.AMOUNT" );

		createAndRunQuery( null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				bindingNameRow,
				bindingExprRow );
		checkOutputFile( );
	}

	/**
	 * Test feature of incorrect filter expression, throw exception
	 */
	public void test5_IncorrectFilterExpression( ) throws Exception
	{
		String[] bindingNameGroup = new String[2];
		bindingNameGroup[0] = "GROUP_COUNTRY";
		bindingNameGroup[1] = "GROUP_CITY";
		
		IBaseExpression[] bindingGrpEpre = new IBaseExpression[]{
				
		        new ScriptExpression("dataSetRow.COUNTRY"), 
		        new ScriptExpression("dataSetRow.CITY")};
		
		GroupDefinition[] groupDefn = new GroupDefinition[]{
				new GroupDefinition( "group0"), new GroupDefinition("Group1" )};
		groupDefn[0].setKeyExpression( "row.COUNTRY" );
		groupDefn[1].setKeyExpression( "row.CITY" );

		String[] bindingNameSort = new String[]{
				"testSortName"
		};
		IBaseExpression[] sortExprName = new IBaseExpression[]{
				new ScriptExpression("sort_ec")
		};
		
		SortDefinition[] sortDefn = new SortDefinition[]{new SortDefinition( )};
		sortDefn[0].setColumn( "SALE_DATE" );
		sortDefn[0].setSortDirection( ISortDefinition.SORT_DESC );

		
		
		String[] bindingNameRow = new String[4];		
		bindingNameRow[0] = "ROW_COUNTRY";
		bindingNameRow[1] = "ROW_CITY";
		bindingNameRow[2] = "ROW_SALE_DATE";
		bindingNameRow[3] = "ROW_AMOUNT";
		IBaseExpression[] bindingExprRow = new IBaseExpression[4];
		bindingExprRow[0] = new ScriptExpression( "dataSetRow.COUNTRY" );
		bindingExprRow[1] = new ScriptExpression( "dataSetRow.CITY" );
		bindingExprRow[2] = new ScriptExpression( "dataSetRow.SALE_DATE" );
		bindingExprRow[3] = new ScriptExpression( "dataSetRow.AMOUNT" );

		// wrong operator
		String[] bindingNameFilter = new String[1];
		bindingNameFilter[0] = "SALE_FILTER";
		IBaseExpression[] bindingExprFilter = new IBaseExpression[1];
		bindingExprFilter[0] = new ScriptExpression( "dataSetRow.AMONT && 100" );
		FilterDefinition[] filters = new FilterDefinition[]{new FilterDefinition(
				new ScriptExpression( "row.SALE_FILTER_E" ) )};

		try
		{
			createAndRunQuery( bindingNameGroup,
					bindingGrpEpre,
					groupDefn,
					bindingNameSort,
					sortExprName,
					sortDefn,
					bindingNameFilter,
					bindingExprFilter,
					filters,
					bindingNameRow,
					bindingExprRow );
			fail( "Should throw DteException!" );
		}
		catch ( DataException e )
		{
			// TODO: verify that e has correct error code
		}
	}

	/**
	 * Test feature of group, sort, ConditionalExpression
	 */
	public void test6_group_sort_ConditionalExpression( ) throws Exception
	{
		String[] bindingNameGroup = new String[]{
				"group_COUNTRY","group_CITY"
		};
		
		IBaseExpression[] bindingExpressionGroup = new IBaseExpression[]{
				new ScriptExpression("dataSetRow.COUNTRY"),
				new ScriptExpression("dataSetRow.CITY")
		};
		
		GroupDefinition[] groupDefn = new GroupDefinition[]{
				new GroupDefinition("GROUP0" ), new GroupDefinition( "GROUP1")};
		groupDefn[0].setKeyExpression( "row.group_COUNTRY" );//???do not changed
		groupDefn[1].setKeyExpression( "row.group_CITY" );//need same value from bindingNameGroup

		String[] bindingNameSort = new String[]{
				"Sort_binding_Name"
		};
		
		IBaseExpression[] bindingExprSort = new IBaseExpression[]{
				new ScriptExpression("dataSetRow.SALE_DATE" )
		};
		SortDefinition[] sortDefn = new SortDefinition[]{new SortDefinition( )};
		sortDefn[0].setColumn( "Sort_binding_Name" );//need same value from bindingNameSort
		sortDefn[0].setSortDirection( ISortDefinition.SORT_DESC );
		
		String[] bindingNameRow = new String[9];		
		bindingNameRow[0] = "ROW_COUNTRY";
		bindingNameRow[1] = "ROW_CITY";
		bindingNameRow[2] = "ROW_SALE_DATE";
		bindingNameRow[3] = "ROW_AMOUNT";		
		bindingNameRow[4] = "ROW_AMOUNT_2";
		bindingNameRow[5] = "ROW_CITY_2";
		bindingNameRow[6] = "ROW_CITY_3";
		bindingNameRow[7] = "ROW_SALE_DATE_2";
		bindingNameRow[8] = "ROW_AMOUNT_4";		
		IBaseExpression[] bindingExprRow = new IBaseExpression[]{
				new ScriptExpression( "dataSetRow.COUNTRY", 0 ),
				new ScriptExpression( "dataSetRow.CITY", 0 ),
				new ScriptExpression( "dataSetRow.SALE_DATE", 0 ),
				new ScriptExpression( "dataSetRow.AMOUNT", 0 ),
				new ConditionalExpression( "dataSetRow.AMOUNT",
						ConditionalExpression.OP_GT,
						"5" ),
				new ConditionalExpression( "dataSetRow.CITY",
						ConditionalExpression.OP_EQ,
						"'Beijing'" ),
				new ConditionalExpression( "dataSetRow.CITY",
						ConditionalExpression.OP_NE,
						"'Beijing'" ),
				new ConditionalExpression( "dataSetRow.SALE_DATE",
						ConditionalExpression.OP_GE,
						"'01/01/2004'" ),
				new ConditionalExpression( "dataSetRow.AMOUNT",
						ConditionalExpression.OP_BETWEEN,
						"5",
						"100" )
		};
		
		createAndRunQuery( bindingNameGroup,
				bindingExpressionGroup,
				groupDefn,
				bindingNameSort,
				bindingExprSort,
				sortDefn,
				null,
				null,
				null,
				bindingNameRow,
				bindingExprRow );
		checkOutputFile( );
	}

	/**
	 * Regression Test for SRC #78568 Filetr on date time doesn't work properly
	 */
	public void Regressiontest78568( ) throws Exception
	{
		String[] bindingNameGroup = new String[2];
		bindingNameGroup[0] = "GROUP_COUNTRY";
		bindingNameGroup[1] = "GROUP_CITY";
		IBaseExpression[] bindingExprGroup = new IBaseExpression[2];
		bindingExprGroup[0] = new ScriptExpression( "dataSetRow.COUNTRY" );
		bindingExprGroup[1] = new ScriptExpression( "dataSetRow.CITY" );		
		GroupDefinition[] groupDefn = new GroupDefinition[]{new GroupDefinition( "group0"),
				new GroupDefinition("group1" )};
		groupDefn[0].setKeyExpression( "row.GROUP_COUNTRY" );
		groupDefn[1].setKeyExpression( "row.GROUP_CITY" );
		
		String[] bindingNameSort = new String[1];
		bindingNameSort[0] = "SORT_SALE_DATE";
		IBaseExpression[] bindingExprSort = new IBaseExpression[1];
		bindingExprSort[0] = new ScriptExpression( "dataSetRow.SALE_DATE" );		
		SortDefinition[] sortDefn = new SortDefinition[]{new SortDefinition( )};
		sortDefn[0].setColumn( "SORT_SALE_DATE" );
		sortDefn[0].setSortDirection( ISortDefinition.SORT_DESC );

		String[] bindingNameFilter = new String[1];
		bindingNameFilter[0] = "FILTER_SALE_DATE";
		IBaseExpression[] bindingExprFilter = new IBaseExpression[1];
		bindingExprFilter[0] = new ScriptExpression( "dataSetRow.SALE_DATE" );
		FilterDefinition[] filterDefn = new FilterDefinition[]{
			new FilterDefinition( new ConditionalExpression( "row.FILTER_SALE_DATE",
					ConditionalExpression.OP_GE,
					"'2004-03-19 00:00:00.0'" ) )
		};

		String[] bindingNameRow = new String[4];		
		bindingNameRow[0] = "ROW_COUNTRY";
		bindingNameRow[1] = "ROW_CITY";
		bindingNameRow[2] = "ROW_SALE_DATE";
		bindingNameRow[3] = "ROW_AMOUNT";
		IBaseExpression[] bindingExprRow = new IBaseExpression[4];
		bindingExprRow[0] = new ScriptExpression( "dataSetRow.COUNTRY" );
		bindingExprRow[1] = new ScriptExpression( "dataSetRow.CITY" );
		bindingExprRow[2] = new ScriptExpression( "dataSetRow.SALE_DATE" );
		bindingExprRow[3] = new ScriptExpression( "dataSetRow.AMOUNT" );
		
		createAndRunQuery( bindingNameGroup,
				bindingExprGroup,
				groupDefn,
				bindingNameSort,
				bindingExprSort,
				sortDefn,
				bindingNameFilter,
				bindingExprFilter,
				filterDefn,
				bindingNameRow,
				bindingExprRow );
		checkOutputFile( );
	}

	/**
	 * Test feature of group, sort, filter
	 */
	public void test7_group_sort_filter( ) throws Exception
	{
		String[] bindingNameGroup = new String[2];
		bindingNameGroup[0] = "gCOUNTRY";
		bindingNameGroup[1] = "gCITY";
		IBaseExpression[] bindingExprGroup = new IBaseExpression[2];
		bindingExprGroup[0] = new ScriptExpression( "dataSetRow.COUNTRY" );
		bindingExprGroup[1] = new ScriptExpression( "dataSetRow.CITY" );
		
		GroupDefinition[] groupDefn = new GroupDefinition[]{
				new GroupDefinition( ), new GroupDefinition( )};
		groupDefn[0].setKeyExpression( "row.gCOUNTRY" );
		groupDefn[1].setKeyExpression( "row.gCITY" );

		String[] bindingNameSort = new String[1];
		bindingNameSort[0] = "SORT_SALE_DATE";
		IBaseExpression[] bindingExprSort = new IBaseExpression[1];
		bindingExprSort[0] = new ScriptExpression( "dataSetRow.SALE_DATE" );
		
		SortDefinition[] sortDefn = new SortDefinition[]{new SortDefinition( )};
		sortDefn[0].setColumn( "SORT_SALE_DATE" );
		sortDefn[0].setSortDirection( ISortDefinition.SORT_DESC );

		String[] bindingNameFilter = new String[1];
		bindingNameFilter[0] = "FILTER_AMOUNT";
		IBaseExpression[] bindingExprFilter = new IBaseExpression[1];
		bindingExprFilter[0] = new ScriptExpression( "dataSetRow.AMOUNT" );
		FilterDefinition[] filters = new FilterDefinition[]{new FilterDefinition(
				new ConditionalExpression( "dataSetRow.AMOUNT",
						ConditionalExpression.OP_GT, "400" ) )};
		
		String[] bindingNameRow = new String[4];		
		bindingNameRow[0] = "ROW_COUNTRY";
		bindingNameRow[1] = "ROW_CITY";
		bindingNameRow[2] = "ROW_SALE_DATE";
		bindingNameRow[3] = "ROW_AMOUNT";
		IBaseExpression[] bindingExprRow = new IBaseExpression[4];
		bindingExprRow[0] = new ScriptExpression( "dataSetRow.COUNTRY" );
		bindingExprRow[1] = new ScriptExpression( "dataSetRow.CITY" );
		bindingExprRow[2] = new ScriptExpression( "dataSetRow.SALE_DATE" );
		bindingExprRow[3] = new ScriptExpression( "dataSetRow.AMOUNT" );

		createAndRunQuery( bindingNameGroup,
				bindingExprGroup,
				groupDefn,
				bindingNameSort,
				bindingExprSort,
				sortDefn,
				bindingNameFilter,
				bindingExprFilter,
				filters,
				bindingNameRow,
				bindingExprRow );
		checkOutputFile( );
	}

	/**
	 * Test feature of duplicate column name from different tables
	 */
	public void test10_DuplicateColName( ) throws Exception
	{
		// Test a SQL with duplicate column name (quite common with join data
		// sets)
		String testSQL = "select COUNTRY, COUNTRY, CITY from "
				+ getTestTableName( );
		( (OdaDataSetDesign) this.dataSet ).setQueryText( testSQL );

		String[] bindingNameRow = new String[]{
				"Row_COUNTRY","Row_CITY"
		};
		
		IBaseExpression[] bindingExprRow = new IBaseExpression[]{
				new ScriptExpression("dataSetRow.COUNTRY"),
				new ScriptExpression("dataSetRow.CITY"),
		};

		QueryDefinition queryDefn = this.createQuery( null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				bindingNameRow,
				bindingExprRow );

		IPreparedQuery preparedQuery = dataEngine.prepare( queryDefn );
		IQueryResults queryResults = preparedQuery.execute( null );
		IResultIterator resultIt = queryResults.getResultIterator( );
		assertTrue( resultIt.next( ) );
	}

	/**
	 * Test feature of GetParameterMetaData
	 * 
	 * @throws Exception
	 */
	public void testBasicGetParameterMetaData( ) throws Exception
	{
		String sql = "select COUNTRY, CITY from " + getTestTableName( )
				+ " where city = ?";
		( (OdaDataSetDesign) this.dataSet ).setQueryText( sql );
		

		QueryDefinition queryDefn = newReportQuery( );

		IPreparedQuery preparedQuery = dataEngine.prepare( queryDefn );
		Collection parameterMetaData = preparedQuery.getParameterMetaData( );
		assertTrue( parameterMetaData != null && parameterMetaData.size( ) == 1 );

		Iterator iter = parameterMetaData.iterator( );
		while ( iter.hasNext( ) )
		{
			IParameterMetaData paramMd = (IParameterMetaData) iter.next( );
			assertEquals( 1, paramMd.getPosition( ) );
			assertEquals( DataType.STRING_TYPE, paramMd.getDataType( ) );
			assertEquals( null, paramMd.getName( ) );
			assertEquals( "VARCHAR", paramMd.getNativeTypeName( ) );
			assertEquals( 0, paramMd.getScale( ) );
			assertEquals( 10, paramMd.getPrecision( ) );
		}
	}

	/**
	 * Test feature of GetParameterMetaData1
	 * 
	 * @throws Exception
	 */
	public void testBasicGetParameterMetaData1( ) throws Exception
	{
		String sql = "select COUNTRY, CITY from " + getTestTableName( )
				+ " where city = ?";
		( (OdaDataSetDesign) this.dataSet ).setQueryText( sql );

		// add an input parameter hint
		ParameterDefinition inputParamDefn = new ParameterDefinition( "param1",
				DataType.DECIMAL_TYPE, true, false );
		inputParamDefn.setPosition( 1 );
		inputParamDefn.setDefaultInputValue( "0" );
		( (OdaDataSetDesign) this.dataSet ).addParameter( inputParamDefn );

		IBaseExpression[] expressions = new IBaseExpression[]{
				new ScriptExpression( "row.COUNTRY", 0 ),
				new ScriptExpression( "row.CITY", 0 )};

		QueryDefinition queryDefn = newReportQuery( );

		IPreparedQuery preparedQuery = dataEngine.prepare( queryDefn );
		Collection parameterMetaData = preparedQuery.getParameterMetaData( );
		assertTrue( parameterMetaData != null && parameterMetaData.size( ) == 1 );

		Iterator iter = parameterMetaData.iterator( );
		while ( iter.hasNext( ) )
		{
			IParameterMetaData paramMd = (IParameterMetaData) iter.next( );
			assertEquals( 1, paramMd.getPosition( ) );
			assertEquals( DataType.STRING_TYPE, paramMd.getDataType( ) );
			assertEquals( "param1", paramMd.getName( ) );
			assertEquals( "VARCHAR", paramMd.getNativeTypeName( ) );
			assertEquals( 0, paramMd.getScale( ) );
			assertEquals( 10, paramMd.getPrecision( ) );
		}
	}

	/**
	 * Test feature of GetParameterMetaDataDefaultValue
	 * 
	 * @throws Exception
	 */
	public void testBasicGetParameterMetaDataDefaultValue( ) throws Exception
	{
		String sql = "select COUNTRY, CITY from " + getTestTableName( )
				+ " where city = ?";
		( (OdaDataSetDesign) this.dataSet ).setQueryText( sql );

		// add an input parameter hint
		ParameterDefinition inputParamDefn = new ParameterDefinition( "param1",
				DataType.DECIMAL_TYPE );
		inputParamDefn.setInputMode( true );
		inputParamDefn.setDefaultInputValue( "123" );
		inputParamDefn.setPosition( 1 );

		( (OdaDataSetDesign) this.dataSet ).addParameter( inputParamDefn );

		IBaseExpression[] expressions = new IBaseExpression[]{
				new ScriptExpression( "row.COUNTRY", 0 ),
				new ScriptExpression( "row.CITY", 0 )};

		QueryDefinition queryDefn = newReportQuery( );

		IPreparedQuery preparedQuery = dataEngine.prepare( queryDefn );
		Collection parameterMetaData = preparedQuery.getParameterMetaData( );
		assertTrue( parameterMetaData != null && parameterMetaData.size( ) == 1 );

		Iterator iter = parameterMetaData.iterator( );
		while ( iter.hasNext( ) )
		{
			IParameterMetaData paramMd = (IParameterMetaData) iter.next( );
			assertEquals( 1, paramMd.getPosition( ) );
			assertEquals( DataType.STRING_TYPE, paramMd.getDataType( ) );
			assertEquals( "param1", paramMd.getName( ) );
			assertEquals( "VARCHAR", paramMd.getNativeTypeName( ) );
			assertEquals( 0, paramMd.getScale( ) );
			assertEquals( 10, paramMd.getPrecision( ) );
			assertEquals( "123", paramMd.getDefaultInputValue( ) );
		}
	}

	/**
	 * Test feature of NativeColumnTypeName
	 * 
	 * @throws Exception
	 */
	public void testNativeColumnTypeName( ) throws Exception
	{
		String testSQL = "select COUNTRY, CITY from " + getTestTableName( );
		( (OdaDataSetDesign) this.dataSet ).setQueryText( testSQL );

		IBaseExpression[] expressions = new IBaseExpression[]{
				new ScriptExpression( "row.COUNTRY", 0 ),
				new ScriptExpression( "row.CITY", 0 )};

		QueryDefinition queryDefn = newReportQuery( );

		IPreparedQuery preparedQuery = dataEngine.prepare( queryDefn );
		IQueryResults queryResults = preparedQuery.execute( null );
		IResultMetaData metadata = queryResults.getResultMetaData( );

		assertEquals( "VARCHAR", metadata.getColumnNativeTypeName( 1 ) );
		assertEquals( "VARCHAR", metadata.getColumnNativeTypeName( 2 ) );
	}

	/**
	 * Create query definition from passed parameteres and then run it.
	 * 
	 * @param expressions
	 * @param groupDefn
	 * @param sortDefn
	 * @param filters
	 * @throws Exception
	 */
	
	/**
	 * Create query definition from passed parameters
	 * 
	 * @param expressions
	 *            row expression
	 * @param groupDefn
	 * @param sortDefn
	 * @param filters
	 * @return QueryDefinition
	 */
	}