/*
 //This software is subject to the terms of the Common Public License
 //Agreement, available at the following URL:
 //http://www.opensource.org/licenses/cpl.html.
 //Copyright (C) 2004-2005 TONBELLER AG
 //All Rights Reserved.
 //You must accept the terms of that agreement to use this software.
 */
package mondrian.rolap;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import mondrian.olap.Exp;
import mondrian.olap.FunDef;
import mondrian.olap.MondrianProperties;
import mondrian.olap.NativeEvaluator;
import mondrian.olap.Util;
import mondrian.rolap.sql.SqlQuery;
import mondrian.rolap.sql.TupleConstraint;

/**
 * computes a Filter(set, condition) in SQL
 * 
 * @author av
 * @since Nov 21, 2005
 */
public class RolapNativeFilter extends RolapNativeSet {

    public RolapNativeFilter() {
        super.setEnabled(MondrianProperties.instance().EnableNativeFilter.get());
    }

    class FilterConstraint extends SetConstraint {
        String filterExpr;

        public FilterConstraint(CrossJoinArg[] args, RolapEvaluator evaluator, String filterByExpr) {
            super(args, evaluator, true);
            this.filterExpr = filterByExpr;
        }

        /**
         * we alwas need to join the fact table because we want to evalutate
         * the filter expression against a fact.
         */
        protected boolean isJoinRequired() {
            return true;
        }

        public void addConstraint(SqlQuery sqlQuery) {
            sqlQuery.addHaving(filterExpr);
            super.addConstraint(sqlQuery);
        }

        public Object getCacheKey() {
            List key = new ArrayList();
            key.add(super.getCacheKey());
            key.add(filterExpr);
            return key;
        }
    }

    protected boolean isStrict() {
        return true;
    }

    NativeEvaluator createEvaluator(RolapEvaluator evaluator, FunDef fun, Exp[] args) {
        if (!isEnabled())
            return null;
        // is this "Filter(<set>, <numeric expr>)"
        String funName = fun.getName();
        if (!"Filter".equalsIgnoreCase(funName))
            return null;

        if (args.length != 2)
            return null;

        // extract the set expression
        CrossJoinArg[] cargs = checkCrossJoinArg(args[0]);
        if (cargs == null)
            return null;
        if (isPreferInterpreter(cargs))
            return null;

        // extract "order by" expression
        RolapSchemaReader schemaReader = (RolapSchemaReader) evaluator.getSchemaReader();
        DataSource ds = schemaReader.getDataSource();
        Connection con = null;
        try {
            con = ds.getConnection();

            // generate the WHERE condition
            SqlQuery sqlQuery = SqlTupleReader.newQuery(con, "NativeFilter");
            RolapNativeSql sql = new RolapNativeSql(sqlQuery);
            String filterExpr = sql.generateFilterCondition(args[1]);
            if (filterExpr == null)
                return null;

            LOGGER.info("using native filter");

            TupleConstraint constraint = new FilterConstraint(cargs, evaluator, filterExpr);
            return new SetEvaluator(cargs, schemaReader, constraint);
        } catch (SQLException e) {
            throw Util.newInternal(e, "RolapNativeFilter");
        } finally {
            if (con != null) {
                try {
                    con.close();
                } catch (SQLException e) {
                    LOGGER.error(null, e);
                }
            }
        }
    }

}

@@ -753,17 +753,16 @@
 n SQL%0A *
- 
 %0A * @aut
@@ -2734,24 +2734,332 @@
 nection();%0A%0A
+            // Disable filters against Derby, because its HAVING support is%0A            // crippled. See bug 1379182.%0A            final SqlQuery.Dialect dialect =%0A                    SqlQuery.Dialect.create(con.getMetaData());%0A            if (dialect.isDerby()) %7B%0A                return null;%0A            %7D%0A%0A
             
@@ -3086,24 +3086,24 @@
 E condition%0A
-
             
@@ -3328,32 +3328,34 @@
 terExpr == null)
+ %7B
 %0A               
@@ -3360,32 +3360,45 @@
    return null;%0A
+            %7D
 %0A            LOG

Disable native filters in Derby, pending Anatoly's fix. See sfbug 1379182.