001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.internal.query;
022:
023: import java.lang.reflect.Constructor;
024:
025: import com.db4o.ObjectContainer;
026: import com.db4o.ObjectSet;
027: import com.db4o.diagnostic.NativeQueryOptimizerNotLoaded;
028: import com.db4o.foundation.Iterator4;
029: import com.db4o.foundation.Iterator4Impl;
030: import com.db4o.foundation.List4;
031: import com.db4o.internal.*;
032: import com.db4o.internal.diagnostic.DiagnosticProcessor;
033: import com.db4o.query.Predicate;
034: import com.db4o.query.Query;
035: import com.db4o.query.QueryComparator;
036: import com.db4o.reflect.Reflector;
037:
038: /**
039: * @sharpen.ignore
040: */
041: public class NativeQueryHandler {
042:
043: private static final String OPTIMIZER_IMPL_NAME = "com.db4o.nativequery.optimization.Db4oOnTheFlyEnhancer";
044:
045: public final static String UNOPTIMIZED = "UNOPTIMIZED";
046: public final static String PREOPTIMIZED = "PREOPTIMIZED";
047: public final static String DYNOPTIMIZED = "DYNOPTIMIZED";
048:
049: private ObjectContainer _container;
050: private Db4oNQOptimizer _enhancer;
051: private List4 _listeners;
052:
053: public NativeQueryHandler(ObjectContainer container) {
054: _container = container;
055: loadQueryOptimizer();
056: }
057:
058: public void addListener(Db4oQueryExecutionListener listener) {
059: _listeners = new List4(_listeners, listener);
060: }
061:
062: public void clearListeners() {
063: _listeners = null;
064: }
065:
066: public ObjectSet execute(Query query, Predicate predicate,
067: QueryComparator comparator) {
068: return configureQuery(query, predicate, comparator).execute();
069: }
070:
071: private Query configureQuery(Query query, Predicate predicate,
072: QueryComparator comparator) {
073: if (comparator != null) {
074: query.sortBy(comparator);
075: }
076: query.constrain(predicate.extentType());
077: if (predicate instanceof Db4oEnhancedFilter) {
078: ((Db4oEnhancedFilter) predicate).optimizeQuery(query);
079: notifyListeners(predicate, NativeQueryHandler.PREOPTIMIZED,
080: null);
081: return query;
082: }
083: try {
084: if (shouldOptimize()) {
085: Object optimized = _enhancer.optimize(query, predicate);
086: notifyListeners(predicate,
087: NativeQueryHandler.DYNOPTIMIZED, optimized);
088: return query;
089: }
090: } catch (Exception exc) {
091: //exc.printStackTrace();
092: }
093: query.constrain(new PredicateEvaluation(predicate));
094: notifyListeners(predicate, NativeQueryHandler.UNOPTIMIZED, null);
095: if (shouldOptimize()) {
096: DiagnosticProcessor dp = ((ObjectContainerBase) _container)._handlers._diagnosticProcessor;
097: if (dp.enabled()) {
098: dp.nativeQueryUnoptimized(predicate);
099: }
100: }
101: return query;
102: }
103:
104: private boolean shouldOptimize() {
105: return _container.ext().configure().optimizeNativeQueries()
106: && _enhancer != null;
107: }
108:
109: private void notifyListeners(Predicate predicate, String msg,
110: Object optimized) {
111: NQOptimizationInfo info = new NQOptimizationInfo(predicate,
112: msg, optimized);
113: for (Iterator4 iter = new Iterator4Impl(_listeners); iter
114: .moveNext();/**/) {
115: ((Db4oQueryExecutionListener) iter.current())
116: .notifyQueryExecuted(info);
117: }
118: }
119:
120: private void loadQueryOptimizer() {
121: Class clazz = ReflectPlatform
122: .forName(NativeQueryHandler.OPTIMIZER_IMPL_NAME);
123: DiagnosticProcessor dp = ((ObjectContainerBase) _container)._handlers._diagnosticProcessor;
124:
125: if (clazz == null) {
126: if (dp.enabled()) {
127: dp
128: .nativeQueryOptimizerNotLoaded(NativeQueryOptimizerNotLoaded.NQ_NOT_PRESENT);
129: }
130: return;
131: }
132:
133: try {
134: Constructor constructor;
135: constructor = clazz
136: .getConstructor(new Class[] { Reflector.class });
137:
138: if (constructor == null)
139: return;
140:
141: _enhancer = (Db4oNQOptimizer) constructor
142: .newInstance(new Object[] { this ._container.ext()
143: .reflector() });
144: } catch (Exception e) {
145: if (dp.enabled()) {
146: dp
147: .nativeQueryOptimizerNotLoaded(NativeQueryOptimizerNotLoaded.NQ_CONSTRUCTION_FAILED);
148: }
149: }
150:
151: }
152: }
|