KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > rolap > RolapNativeCrossJoin


1 /*
2 // This software is subject to the terms of the Common Public License
3 // Agreement, available at the following URL:
4 // http://www.opensource.org/licenses/cpl.html.
5 // Copyright (C) 2004-2005 TONBELLER AG
6 // All Rights Reserved.
7 // You must accept the terms of that agreement to use this software.
8 */

9 package mondrian.rolap;
10
11 import mondrian.olap.*;
12 import mondrian.olap.fun.*;
13 import mondrian.rolap.sql.TupleConstraint;
14
15 /**
16  * creates a {@link mondrian.olap.NativeEvaluator} that evaluates NON EMPTY
17  * CrossJoin in SQL. The generated SQL will join the dimension tables with
18  * the fact table and return all combinations that have a
19  * corresponding row in the fact table. The current context (slicer) is
20  * used for filtering (WHERE clause in SQL). This very effective computes
21  * queris like
22  * <pre>
23  * select ...
24  * NON EMTPY crossjoin([product].[name].members, [customer].[name].members) on rows
25  * froms [Sales]
26  * where ([store].[store #14])
27  * </pre>
28  * where both, customer.name and product.name have many members, but the resulting
29  * crossjoin only has few.
30  * <p>
31  * The implementation currently can not handle sets containting
32  * parent/child hierarchies, ragged hierarchies, calculated members and
33  * the ALL member. Otherwise all
34  *
35  * @author av
36  * @since Nov 21, 2005
37  */

38 public class RolapNativeCrossJoin extends RolapNativeSet {
39
40     public RolapNativeCrossJoin() {
41         super.setEnabled(MondrianProperties.instance().EnableNativeCrossJoin.get());
42     }
43
44     /**
45      * restricts the result to the current context.
46      *
47      * If the current context contains calculated members, these are silently ignored
48      * which means, that too many members are return. This does not harm, because the
49      * {@link RolapConnection}.NonEmptyResult will filter out these later.
50      *
51      * @author av
52      * @since Nov 17, 2005
53      */

54     static class NonEmptyCrossJoinConstraint extends SetConstraint {
55         NonEmptyCrossJoinConstraint(CrossJoinArg[] args, RolapEvaluator evaluator) {
56             super(args, evaluator, false);
57         }
58
59     }
60
61     protected boolean isStrict() {
62         return false;
63     }
64
65     NativeEvaluator createEvaluator(RolapEvaluator evaluator, FunDef fun, Exp[] args) {
66         if (!isEnabled()) {
67             // native crossjoins were explicitly disabled, so no need
68
// to alert about not using them
69
return null;
70         }
71         RolapCube cube = (RolapCube) evaluator.getCube();
72
73         CrossJoinArg[] cargs = checkCrossJoin(fun, args);
74         if (cargs == null) {
75             // Something in the arguments to the crossjoin prevented
76
// native evaluation; may need to alert
77
alertCrossJoinNonNative(
78                 evaluator,
79                 fun,
80                 "arguments not supported");
81             return null;
82         }
83         if (isPreferInterpreter(cargs)) {
84             // Native evaluation wouldn't buy us anything, so no
85
// need to alert
86
return null;
87         }
88         RolapLevel [] levels = new RolapLevel[cargs.length];
89         for (int i = 0; i < cargs.length; i++) {
90             levels[i] = cargs[i].getLevel();
91         }
92
93         if ((cube.isVirtual() &&
94                 !evaluator.getQuery().nativeCrossJoinVirtualCube())) {
95             // Something in the query at large (namely, some unsupported
96
// function on the [Measures] dimension) prevented native
97
// evaluation with virtual cubes; may need to alert
98
alertCrossJoinNonNative(
99                 evaluator,
100                 fun,
101                 "not all functions on [Measures] dimension supported");
102             return null;
103         }
104         if (!NonEmptyCrossJoinConstraint.isValidContext(
105                 evaluator,
106                 false,
107                 levels)) {
108             // Missing join conditions due to non-conforming dimensions
109
// meant native evaluation would have led to a true cross
110
// product, which we want to defer instead of pushing it down;
111
// so no need to alert
112
return null;
113         }
114
115         // join with fact table will always filter out those members
116
// that dont have a row in the fact table
117
if (!evaluator.isNonEmpty())
118             return null;
119
120         LOGGER.debug("using native crossjoin");
121
122         TupleConstraint constraint = new NonEmptyCrossJoinConstraint(cargs, evaluator);
123         SchemaReader schemaReader = evaluator.getSchemaReader();
124         return new SetEvaluator(cargs, schemaReader, constraint);
125     }
126
127     private void alertCrossJoinNonNative(
128         RolapEvaluator evaluator,
129         FunDef fun,
130         String JavaDoc reason) {
131         if (!(fun instanceof NonEmptyCrossJoinFunDef)) {
132             // Only alert for an explicit NonEmptyCrossJoin,
133
// since query authors use that to indicate that
134
// they expect it to be "wicked fast"
135
return;
136         }
137         if (!evaluator.getQuery().shouldAlertForNonNative(fun)) {
138             return;
139         }
140         RolapUtil.alertNonNative("NonEmptyCrossJoin", reason);
141     }
142 }
143
Popular Tags