callCount++; if (callCount % REPORT_INTERVAL == 0) { LOG.error("Optimiser called " + callCount + " times"); }
    public static String optimise(String query, Database database) throws SQLException {        long start = new Date().getTime();        long parseTime = 0;        // If we want to do any query caching, here is where we should do it.        OptimiserCache cache = OptimiserCache.getInstance(database);        LimitOffsetQuery limitOffsetQuery = new LimitOffsetQuery(query);        //LOG.info("Original Query: " + limitOffsetQuery.getQuery() + ", "        //        + limitOffsetQuery.getLimit() + ", " + limitOffsetQuery.getOffset());        String cachedQuery = cache.lookup(limitOffsetQuery.getQuery(), limitOffsetQuery.getLimit(),                limitOffsetQuery.getOffset());        if (cachedQuery != null) {            LOG.info("Optimising query took " + ((new Date()).getTime() - start)                    + " ms - cache hit: " + query);            return limitOffsetQuery.reconstruct(cachedQuery);        }        try {            Connection explainConnection = database.getConnection();            BestQueryExplainer bestQuery = new BestQueryExplainer(explainConnection);            String optimisedQuery = null;            int expectedRows = 0;            int expectedTime = 0;            try {                // First, add the original string to the BestQuery object, so it has an opportunity                // to say optimisation is not worth it, before parsing.                bestQuery.add(query);                expectedTime = (int) bestQuery.getBestExplainResult().getComplete();                Query originalQuery = new Query(query);                parseTime = new Date().getTime();                remapAliasesToAvoidPrecomputePrefix(originalQuery);                PrecomputedTableManager ptm = PrecomputedTableManager.getInstance(database);                Set precomputedTables = ptm.getPrecomputedTables();                recursiveOptimise(precomputedTables, originalQuery, bestQuery, originalQuery);            } catch (BestQueryException e) {                // Ignore - bestQuery decided to cut short the search                expectedTime = (int) bestQuery.getBestExplainResult().getComplete();            } finally {                explainConnection.close();            }            optimisedQuery = bestQuery.getBestQueryString();            expectedRows = (int) bestQuery.getBestExplainResult().getEstimatedRows();            // Add optimised query to the cache here.            LimitOffsetQuery limitOffsetOptimisedQuery = new LimitOffsetQuery(optimisedQuery);            LOG.info("New cache line produced - expectedRows = " + expectedRows + ", limit = "                    + limitOffsetQuery.getLimit());            cache.addCacheLine(limitOffsetQuery.getQuery(), limitOffsetOptimisedQuery.getQuery(),                    limitOffsetQuery.getLimit(), limitOffsetQuery.getOffset(), expectedRows);            LOG.info("Optimising " + expectedTime + " ms query took "                    + ((new Date()).getTime() - start)                    + (parseTime == 0 ? " ms without parsing " : " ms including "                        + (parseTime - start) + " ms for parse ") + "- cache miss: " + query);            return optimisedQuery;        } catch (RuntimeException e) {            // Query was not acceptable.            LOG.warn("Exception: " + e.toString());        }        LOG.info("Optimising query took " + ((new Date()).getTime() - start)                + " ms - unparsable query: " + query);        return query;    }