EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.table]

COVERAGE SUMMARY FOR SOURCE FILE [Plan.java]

nameclass, %method, %block, %line, %
Plan.java100% (2/2)100% (8/8)100% (271/271)100% (53/53)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Plan100% (1/1)100% (6/6)100% (244/244)100% (49/49)
Plan (TableFilter [], int, Expression): void 100% (1/1)100% (66/66)100% (16/16)
calculateCost (Session): double 100% (1/1)100% (85/85)100% (18/18)
getFilters (): TableFilter [] 100% (1/1)100% (3/3)100% (1/1)
getItem (TableFilter): PlanItem 100% (1/1)100% (6/6)100% (1/1)
removeUnusableIndexConditions (): void 100% (1/1)100% (58/58)100% (9/9)
setEvaluatable (TableFilter, boolean): void 100% (1/1)100% (26/26)100% (4/4)
     
class Plan$1100% (1/1)100% (2/2)100% (27/27)100% (5/5)
Plan$1 (Plan, ArrayList, ArrayList): void 100% (1/1)100% (12/12)100% (1/1)
accept (TableFilter): void 100% (1/1)100% (15/15)100% (4/4)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.table;
7 
8import java.util.ArrayList;
9import java.util.HashMap;
10import org.h2.engine.Session;
11import org.h2.expression.Expression;
12import org.h2.expression.ExpressionVisitor;
13import org.h2.table.TableFilter.TableFilterVisitor;
14import org.h2.util.New;
15 
16/**
17 * A possible query execution plan. The time required to execute a query depends
18 * on the order the tables are accessed.
19 */
20public class Plan {
21 
22    private final TableFilter[] filters;
23    private final HashMap<TableFilter, PlanItem> planItems = New.hashMap();
24    private final Expression[] allConditions;
25    private final TableFilter[] allFilters;
26 
27    /**
28     * Create a query plan with the given order.
29     *
30     * @param filters the tables of the query
31     * @param count the number of table items
32     * @param condition the condition in the WHERE clause
33     */
34    public Plan(TableFilter[] filters, int count, Expression condition) {
35        this.filters = new TableFilter[count];
36        System.arraycopy(filters, 0, this.filters, 0, count);
37        final ArrayList<Expression> allCond = New.arrayList();
38        final ArrayList<TableFilter> all = New.arrayList();
39        if (condition != null) {
40            allCond.add(condition);
41        }
42        for (int i = 0; i < count; i++) {
43            TableFilter f = filters[i];
44            f.visit(new TableFilterVisitor() {
45                @Override
46                public void accept(TableFilter f) {
47                    all.add(f);
48                    if (f.getJoinCondition() != null) {
49                        allCond.add(f.getJoinCondition());
50                    }
51                }
52            });
53        }
54        allConditions = new Expression[allCond.size()];
55        allCond.toArray(allConditions);
56        allFilters = new TableFilter[all.size()];
57        all.toArray(allFilters);
58    }
59 
60    /**
61     * Get the plan item for the given table.
62     *
63     * @param filter the table
64     * @return the plan item
65     */
66    public PlanItem getItem(TableFilter filter) {
67        return planItems.get(filter);
68    }
69 
70    /**
71     * The the list of tables.
72     *
73     * @return the list of tables
74     */
75    public TableFilter[] getFilters() {
76        return filters;
77    }
78 
79    /**
80     * Remove all index conditions that can not be used.
81     */
82    public void removeUnusableIndexConditions() {
83        for (int i = 0; i < allFilters.length; i++) {
84            TableFilter f = allFilters[i];
85            setEvaluatable(f, true);
86            if (i < allFilters.length - 1 ||
87                    f.getSession().getDatabase().getSettings().earlyFilter) {
88                // the last table doesn't need the optimization,
89                // otherwise the expression is calculated twice unnecessarily
90                // (not that bad but not optimal)
91                f.optimizeFullCondition(false);
92            }
93            f.removeUnusableIndexConditions();
94        }
95        for (TableFilter f : allFilters) {
96            setEvaluatable(f, false);
97        }
98    }
99 
100    /**
101     * Calculate the cost of this query plan.
102     *
103     * @param session the session
104     * @return the cost
105     */
106    public double calculateCost(Session session) {
107        double cost = 1;
108        boolean invalidPlan = false;
109        int level = 1;
110        for (TableFilter tableFilter : allFilters) {
111            PlanItem item = tableFilter.getBestPlanItem(session, level++);
112            planItems.put(tableFilter, item);
113            cost += cost * item.cost;
114            setEvaluatable(tableFilter, true);
115            Expression on = tableFilter.getJoinCondition();
116            if (on != null) {
117                if (!on.isEverything(ExpressionVisitor.EVALUATABLE_VISITOR)) {
118                    invalidPlan = true;
119                    break;
120                }
121            }
122        }
123        if (invalidPlan) {
124            cost = Double.POSITIVE_INFINITY;
125        }
126        for (TableFilter f : allFilters) {
127            setEvaluatable(f, false);
128        }
129        return cost;
130    }
131 
132    private void setEvaluatable(TableFilter filter, boolean b) {
133        filter.setEvaluatable(filter, b);
134        for (Expression e : allConditions) {
135            e.setEvaluatable(filter, b);
136        }
137    }
138}

[all classes][org.h2.table]
EMMA 2.0.5312 (C) Vladimir Roubtsov