Source Code Cross Referenced for BasicQueryHandler.java in  » Database-ORM » MMBase » org » mmbase » storage » search » implementation » database » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » MMBase » org.mmbase.storage.search.implementation.database 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:        This software is OSI Certified Open Source Software.
003:        OSI Certified is a certification mark of the Open Source Initiative.
004:
005:        The license (Mozilla version 1.0) can be read at the MMBase site.
006:        See http://www.MMBase.org/license
007:
008:         */
009:        package org.mmbase.storage.search.implementation.database;
010:
011:        import java.sql.*;
012:        import java.util.*;
013:        import javax.sql.DataSource;
014:
015:        import org.mmbase.cache.*;
016:        import org.mmbase.bridge.Field;
017:        import org.mmbase.bridge.NodeManager;
018:        import org.mmbase.core.CoreField;
019:        import org.mmbase.module.core.*;
020:        import org.mmbase.module.database.MultiConnection;
021:        import org.mmbase.storage.implementation.database.DatabaseStorageManager;
022:        import org.mmbase.storage.implementation.database.DatabaseStorageManagerFactory;
023:        import org.mmbase.storage.search.*;
024:        import org.mmbase.util.logging.*;
025:        import org.mmbase.storage.search.implementation.ModifiableQuery;
026:
027:        /**
028:         * Basic implementation using a database.
029:         * Uses a {@link org.mmbase.storage.search.implementation.database.SqlHandler SqlHandler}
030:         * to create SQL string representations of search queries.
031:         * <p>
032:         * In order to execute search queries, these are represented as SQL strings
033:         * by the handler, and in this form executed on the database.
034:         *
035:         * @author Rob van Maris
036:         * @version $Id: BasicQueryHandler.java,v 1.62 2007/10/22 08:42:40 nklasens Exp $
037:         * @since MMBase-1.7
038:         */
039:        public class BasicQueryHandler implements  SearchQueryHandler {
040:
041:            /** Empty StepField array. */
042:            private static final StepField[] STEP_FIELD_ARRAY = new StepField[0];
043:
044:            private static final Logger log = Logging
045:                    .getLoggerInstance(BasicQueryHandler.class);
046:
047:            /** Sql handler used to generate SQL statements. */
048:            private SqlHandler sqlHandler = null;
049:
050:            /** MMBase instance. */
051:            private MMBase mmbase = null;
052:
053:            /**
054:             * Default constructor.
055:             *
056:             * @param sqlHandler The handler use to create SQL string representations
057:             *        of search queries.
058:             */
059:            public BasicQueryHandler(SqlHandler sqlHandler) {
060:                this .sqlHandler = sqlHandler;
061:                mmbase = MMBase.getMMBase();
062:            }
063:
064:            // javadoc is inherited
065:            public List<MMObjectNode> getNodes(SearchQuery query,
066:                    MMObjectBuilder builder) throws SearchQueryException {
067:
068:                List<MMObjectNode> results;
069:                Connection con = null;
070:                PreparedStatement stmt = null;
071:                String sqlString = null;
072:
073:                try {
074:                    // Flag, set if offset must be supported by skipping results.
075:                    boolean mustSkipResults = (query.getOffset() != SearchQuery.DEFAULT_OFFSET)
076:                            && (sqlHandler.getSupportLevel(
077:                                    SearchQueryHandler.FEATURE_OFFSET, query) == SearchQueryHandler.SUPPORT_NONE);
078:
079:                    // Flag, set if sql handler supports maxnumber.
080:                    boolean sqlHandlerSupportsMaxNumber = sqlHandler
081:                            .getSupportLevel(
082:                                    SearchQueryHandler.FEATURE_MAX_NUMBER,
083:                                    query) != SearchQueryHandler.SUPPORT_NONE;
084:
085:                    // report about offset and max support (for debug purposes)
086:                    if (log.isDebugEnabled()) {
087:                        log
088:                                .debug("Database offset support = "
089:                                        + (sqlHandler
090:                                                .getSupportLevel(
091:                                                        SearchQueryHandler.FEATURE_OFFSET,
092:                                                        query) != SearchQueryHandler.SUPPORT_NONE));
093:                        log.debug("mustSkipResults = " + mustSkipResults);
094:                        log.debug("Database max support = "
095:                                + sqlHandlerSupportsMaxNumber);
096:                    }
097:
098:                    sqlString = createSqlString(query, mustSkipResults,
099:                            sqlHandlerSupportsMaxNumber);
100:
101:                    if (log.isDebugEnabled()) {
102:                        log.debug("sql: " + sqlString);
103:                    }
104:
105:                    // Execute the SQL... ARGH !!! Has to move!
106:                    // get connection...
107:                    DataSource dataSource = ((DatabaseStorageManagerFactory) mmbase
108:                            .getStorageManagerFactory()).getDataSource();
109:                    con = dataSource.getConnection();
110:                    ResultSet rs = null;
111:                    try {
112:                        stmt = con.prepareStatement(sqlString);
113:                        rs = stmt.executeQuery();
114:                        if (mustSkipResults) {
115:                            log
116:                                    .debug("skipping results, to provide weak support for offset");
117:                            for (int i = 0; i < query.getOffset(); i++) {
118:                                rs.next();
119:                            }
120:                        }
121:
122:                        // Now store results as cluster-/real nodes.
123:                        StepField[] fields = query.getFields().toArray(
124:                                STEP_FIELD_ARRAY);
125:                        int maxNumber = query.getMaxNumber();
126:
127:                        // now, we dispatch the reading of the result set to the right function wich instantiates Nodes of the right type.
128:                        if (builder instanceof  ClusterBuilder) {
129:                            results = readNodes((ClusterBuilder) builder,
130:                                    fields, rs, sqlHandlerSupportsMaxNumber,
131:                                    maxNumber, query.getSteps().size());
132:                        } else if (builder instanceof  ResultBuilder) {
133:                            results = readNodes((ResultBuilder) builder,
134:                                    fields, rs, sqlHandlerSupportsMaxNumber,
135:                                    maxNumber);
136:                        } else {
137:                            results = readNodes(builder, fields, rs,
138:                                    sqlHandlerSupportsMaxNumber, maxNumber);
139:                        }
140:                    } finally {
141:                        if (rs != null) {
142:                            rs.close();
143:                        }
144:                    }
145:                } catch (SQLException e) {
146:                    // Something went wrong, log exception
147:                    // and rethrow as SearchQueryException.
148:                    if (log.isDebugEnabled()) {
149:                        log.debug("Query failed:" + query + "\n" + e
150:                                + Logging.stackTrace(e));
151:                    }
152:                    if (con instanceof  MultiConnection) {
153:                        log.debug("Calling check after exception");
154:                        try {
155:                            ((MultiConnection) con).checkAfterException();
156:                        } catch (SQLException sqe) {
157:                            log.debug(sqe);
158:                        }
159:                    } else {
160:                        log.debug("Not a multiconnection");
161:                    }
162:                    throw new SearchQueryException("Query '"
163:                            + (sqlString == null ? "" + query.toString()
164:                                    : sqlString) + "' failed: "
165:                            + e.getClass().getName() + ": " + e.getMessage(), e);
166:                } finally {
167:                    closeConnection(con, stmt);
168:                }
169:
170:                return results;
171:            }
172:
173:            /**
174:             * Safely close a database connection and/or a database statement.
175:             * @param con The connection to close. Can be <code>null</code>.
176:             * @param stmt The statement to close, prior to closing the connection. Can be <code>null</code>.
177:             */
178:            protected void closeConnection(Connection con, Statement stmt) {
179:                try {
180:                    if (stmt != null) {
181:                        stmt.close();
182:                    }
183:                } catch (Exception g) {
184:                }
185:                try {
186:                    if (con != null) {
187:                        con.close();
188:                    }
189:                } catch (Exception g) {
190:                }
191:            }
192:
193:            /**
194:             * Makes a String of a query, taking into consideration if the database supports offset and
195:             * maxnumber features. The resulting String is an SQL query which can be fed to the database.
196:             * @param query the query to convert to sql
197:             * @return the sql string
198:             * @throws SearchQueryException when error occurs while making the string
199:             */
200:            public String createSqlString(SearchQuery query)
201:                    throws SearchQueryException {
202:                // Flag, set if offset must be supported by skipping results.
203:                boolean mustSkipResults = (query.getOffset() != SearchQuery.DEFAULT_OFFSET)
204:                        && (sqlHandler.getSupportLevel(
205:                                SearchQueryHandler.FEATURE_OFFSET, query) == SearchQueryHandler.SUPPORT_NONE);
206:
207:                // Flag, set if sql handler supports maxnumber.
208:                boolean sqlHandlerSupportsMaxNumber = sqlHandler
209:                        .getSupportLevel(SearchQueryHandler.FEATURE_MAX_NUMBER,
210:                                query) != SearchQueryHandler.SUPPORT_NONE;
211:
212:                // report about offset and max support (for debug purposes)
213:                if (log.isDebugEnabled()) {
214:                    log
215:                            .debug("Database offset support = "
216:                                    + (sqlHandler.getSupportLevel(
217:                                            SearchQueryHandler.FEATURE_OFFSET,
218:                                            query) != SearchQueryHandler.SUPPORT_NONE));
219:                    log.debug("mustSkipResults = " + mustSkipResults);
220:                    log.debug("Database max support = "
221:                            + sqlHandlerSupportsMaxNumber);
222:                }
223:
224:                return createSqlString(query, mustSkipResults,
225:                        sqlHandlerSupportsMaxNumber);
226:            }
227:
228:            /**
229:             * Makes a String of a query, taking into consideration if the database supports offset and
230:             * maxnumber features. The resulting String is an SQL query which can be fed to the database.
231:             */
232:
233:            private String createSqlString(SearchQuery query,
234:                    boolean mustSkipResults, boolean sqlHandlerSupportsMaxNumber)
235:                    throws SearchQueryException {
236:                int maxNumber = query.getMaxNumber();
237:                // Flag, set if maxnumber must be supported by truncating results.
238:                boolean mustTruncateResults = (maxNumber != SearchQuery.DEFAULT_MAX_NUMBER)
239:                        && (!sqlHandlerSupportsMaxNumber);
240:                String sqlString;
241:                if (mustSkipResults) { // offset not supported, but needed
242:                    log
243:                            .debug("offset used in query and not supported in database.");
244:                    ModifiableQuery modifiedQuery = new ModifiableQuery(query);
245:                    modifiedQuery.setOffset(SearchQuery.DEFAULT_OFFSET);
246:
247:                    if (mustTruncateResults) {
248:                        log
249:                                .debug("max used in query but not supported in database.");
250:                        // Weak support for offset, weak support for maxnumber:
251:                        modifiedQuery
252:                                .setMaxNumber(SearchQuery.DEFAULT_MAX_NUMBER); // apply no maximum, but truncate result
253:                    } else if (maxNumber != SearchQuery.DEFAULT_MAX_NUMBER) {
254:                        log
255:                                .debug("max used in query and supported by database.");
256:                        // Because offset is not supported add max with the offset.
257:                        // Weak support for offset, sql handler supports maxnumber:
258:                        modifiedQuery.setMaxNumber(query.getOffset()
259:                                + maxNumber);
260:                    }
261:                    sqlString = sqlHandler.toSql(modifiedQuery, sqlHandler);
262:
263:                } else {
264:                    log
265:                            .debug("offset not used or offset is supported by the database.");
266:                    if (mustTruncateResults) {
267:                        log
268:                                .debug("max used in query but not supported in database.");
269:                        // Sql handler supports offset, or not offset is specified.
270:                        // weak support for maxnumber:
271:                        ModifiableQuery modifiedQuery = new ModifiableQuery(
272:                                query);
273:                        modifiedQuery
274:                                .setMaxNumber(SearchQuery.DEFAULT_MAX_NUMBER); // apply no maximum, but truncate result
275:                        sqlString = sqlHandler.toSql(modifiedQuery, sqlHandler);
276:                    } else {
277:                        // Offset not used, maxnumber not used.
278:                        log.debug("no need for modifying Query");
279:                        sqlString = sqlHandler.toSql(query, sqlHandler);
280:                    }
281:                }
282:                // TODO: test maximum sql statement length is not exceeded.
283:                return sqlString;
284:            }
285:
286:            /**
287:             * Read the result list and creates a List of ClusterNodes.
288:             */
289:            private List<MMObjectNode> readNodes(ClusterBuilder builder,
290:                    StepField[] fields, ResultSet rs,
291:                    boolean sqlHandlerSupportsMaxNumber, int maxNumber,
292:                    int numberOfSteps) {
293:                List<MMObjectNode> results = new ArrayList<MMObjectNode>();
294:                DatabaseStorageManager storageManager = (DatabaseStorageManager) mmbase
295:                        .getStorageManager();
296:
297:                // Truncate results to provide weak support for maxnumber.
298:                try {
299:                    while (rs.next()
300:                            && (results.size() < maxNumber || maxNumber == -1)) {
301:                        try {
302:                            ClusterNode node = new ClusterNode(builder,
303:                                    numberOfSteps);
304:                            node.start();
305:
306:                            int j = 1;
307:                            // make use of Node-cache to fill fields
308:                            // especially XML-fields can be heavy, otherwise (Documnents must be instantiated)
309:                            for (StepField element : fields) {
310:                                String fieldName = element.getFieldName(); // why not getAlias first?
311:                                Step step = element.getStep();
312:                                String alias = step.getAlias();
313:                                if (alias == null) {
314:                                    // Use tablename as alias when no alias is specified.
315:                                    alias = step.getTableName();
316:                                }
317:                                CoreField field = builder.getField(alias + '.'
318:                                        + fieldName);
319:                                if (field.getType() == Field.TYPE_BINARY)
320:                                    continue;
321:                                Object value = storageManager.getValue(rs, j++,
322:                                        field, false);
323:                                node.storeValue(alias + '.' + fieldName, value);
324:                            }
325:                            node.clearChanged();
326:                            node.finish();
327:                            results.add(node);
328:                        } catch (Exception e) {
329:                            // log error, but continue with other nodes
330:                            log.error(e.getMessage(), e);
331:                        }
332:                    }
333:                } catch (SQLException sqe) {
334:                    // log error, but return results.
335:                    log.error(sqe);
336:                }
337:                return results;
338:            }
339:
340:            /**
341:             * Read the result list and creates a List of ResultNodes
342:             */
343:            private List<MMObjectNode> readNodes(ResultBuilder builder,
344:                    StepField[] fields, ResultSet rs,
345:                    boolean sqlHandlerSupportsMaxNumber, int maxNumber) {
346:                List<MMObjectNode> results = new ArrayList<MMObjectNode>();
347:                DatabaseStorageManager storageManager = (DatabaseStorageManager) mmbase
348:                        .getStorageManager();
349:
350:                // Truncate results to provide weak support for maxnumber.
351:                try {
352:                    while (rs.next()
353:                            && (maxNumber > results.size() || maxNumber == -1)) {
354:                        try {
355:                            ResultNode node = new ResultNode(builder);
356:                            node.start();
357:                            int j = 1;
358:                            for (StepField element : fields) {
359:                                String fieldName = element.getAlias();
360:                                if (fieldName == null) {
361:                                    fieldName = element.getFieldName();
362:                                }
363:                                CoreField field = builder.getField(fieldName);
364:                                if (field != null
365:                                        && field.getType() == Field.TYPE_BINARY)
366:                                    continue;
367:                                Object value = storageManager.getValue(rs, j++,
368:                                        field, false);
369:                                node.storeValue(fieldName, value);
370:                            }
371:                            node.clearChanged();
372:                            node.finish();
373:                            results.add(node);
374:                        } catch (Exception e) {
375:                            // log error, but continue with other nodes
376:                            log.error(e.getMessage(), e);
377:                        }
378:                    }
379:                } catch (SQLException sqe) {
380:                    // log error, but return results.
381:                    log.error(sqe);
382:                }
383:                return results;
384:            }
385:
386:            /**
387:             * Read the result list and creates a List of normal MMObjectNodes.
388:             */
389:            private List<MMObjectNode> readNodes(MMObjectBuilder builder,
390:                    StepField[] fields, ResultSet rs,
391:                    boolean sqlHandlerSupportsMaxNumber, int maxNumber) {
392:                List<MMObjectNode> results = new ArrayList<MMObjectNode>();
393:                DatabaseStorageManager storageManager = (DatabaseStorageManager) mmbase
394:                        .getStorageManager();
395:
396:                boolean storesAsFile = builder
397:                        .getMMBase()
398:                        .getStorageManagerFactory()
399:                        .hasOption(
400:                                org.mmbase.storage.implementation.database.Attributes.STORES_BINARY_AS_FILE);
401:                // determine indices of queried fields
402:                Map<CoreField, Integer> fieldIndices = new HashMap<CoreField, Integer>();
403:                Step nodeStep = fields[0].getStep();
404:                int j = 1;
405:                for (StepField element : fields) {
406:                    if (element.getType() == Field.TYPE_BINARY)
407:                        continue;
408:                    Integer index = Integer.valueOf(j++);
409:                    if (element.getStep() == nodeStep) {
410:                        String fieldName = element.getFieldName();
411:                        CoreField field = builder.getField(fieldName);
412:                        if (field == null) {
413:                            log.warn("Did not find the field '" + fieldName
414:                                    + "' in builder " + builder);
415:                            continue; // could this happen?
416:                        }
417:                        fieldIndices.put(field, index);
418:                    }
419:                }
420:
421:                // Test if ALL fields are queried
422:                StringBuilder missingFields = null;
423:                for (CoreField field : builder
424:                        .getFields(NodeManager.ORDER_CREATE)) {
425:                    if (field.inStorage()) {
426:                        if (field.getType() == Field.TYPE_BINARY)
427:                            continue;
428:                        if (fieldIndices.get(field) == null) {
429:                            if (missingFields == null) {
430:                                missingFields = new StringBuilder(field
431:                                        .getName());
432:                            } else {
433:                                missingFields.append(", ").append(
434:                                        field.getName());
435:                            }
436:                        }
437:                    }
438:                }
439:
440:                // if not all field are queried, this is a virtual node
441:                boolean isVirtual = missingFields != null;
442:                if (isVirtual) {
443:                    log
444:                            .warn("This query returns virtual nodes (not querying: '"
445:                                    + missingFields + "')");
446:                }
447:
448:                // Truncate results to provide weak support for maxnumber.
449:                try {
450:                    NodeCache nodeCache = NodeCache.getCache();
451:                    Cache<Integer, Integer> typeCache = CacheManager
452:                            .getCache("TypeCache");
453:                    int builderType = builder.getObjectType();
454:                    Integer oTypeInteger = Integer.valueOf(builderType);
455:                    while (rs.next()
456:                            && (maxNumber > results.size() || maxNumber == -1)) {
457:                        try {
458:                            /*
459:                             * This while statement does not deal with mmbase inheritance
460:                             * It creates nodes based on the builder passed in. Nodes with
461:                             * subtypes of this builder are only filled with the field values
462:                             * of this builder. Builders of a subtype are not stored in the nodeCache
463:                             * to limit the time scope of these nodes, because they are not complete.
464:                             */
465:
466:                            MMObjectNode node;
467:                            if (!isVirtual) {
468:                                node = new MMObjectNode(builder, false);
469:                            } else {
470:                                node = new VirtualNode(builder);
471:                            }
472:                            node.start();
473:                            for (CoreField field : builder
474:                                    .getFields(NodeManager.ORDER_CREATE)) {
475:                                if (!field.inStorage())
476:                                    continue;
477:                                Integer index = fieldIndices.get(field);
478:                                Object value = null;
479:                                String fieldName = field.getName();
480:                                if (index != null) {
481:                                    value = storageManager.getValue(rs, index
482:                                            .intValue(), field, true);
483:                                } else {
484:                                    java.sql.Blob b = null;
485:                                    if (field.getType() == Field.TYPE_BINARY
486:                                            && storesAsFile) {
487:                                        log
488:                                                .debug("Storage did not return data for '"
489:                                                        + fieldName
490:                                                        + "', supposing it on disk");
491:                                        // must have been a explicitely specified 'blob' field
492:                                        b = storageManager.getBlobValue(node,
493:                                                field, true);
494:                                    } else if (field.getType() == Field.TYPE_BINARY) {
495:                                        // binary fields never come directly from the database
496:                                        value = MMObjectNode.VALUE_SHORTED;
497:                                    } else if (!isVirtual) {
498:                                        // field wasn't returned by the db - this must be a Virtual node, otherwise fail!
499:                                        // (this shoudln't occur)
500:                                        throw new IllegalStateException(
501:                                                "Storage did not return data for field '"
502:                                                        + fieldName + "'");
503:                                    }
504:                                    if (b != null) {
505:                                        if (b.length() == -1) {
506:                                            value = MMObjectNode.VALUE_SHORTED;
507:                                        } else {
508:                                            value = b.getBytes(0L, (int) b
509:                                                    .length());
510:                                        }
511:                                    }
512:                                }
513:                                node.storeValue(fieldName, value);
514:                            }
515:                            node.clearChanged();
516:                            node.finish();
517:
518:                            // The following code fills the type- and node-cache as far as this is possible at this stage.
519:                            // (provided the node is persistent)
520:                            if (!isVirtual) {
521:                                int otype = node.getOType();
522:                                Integer number = Integer.valueOf(node
523:                                        .getNumber());
524:                                if (otype == builderType) {
525:                                    MMObjectNode cacheNode = nodeCache
526:                                            .get(number);
527:                                    if (cacheNode != null) {
528:                                        node = cacheNode;
529:                                    } else {
530:                                        nodeCache.put(number, node);
531:                                    }
532:                                    typeCache.put(number, oTypeInteger);
533:                                } else {
534:                                    typeCache.put(number, Integer
535:                                            .valueOf(otype));
536:                                }
537:                            }
538:
539:                            results.add(node);
540:                        } catch (Exception e) {
541:                            // log error, but continue with other nodes
542:                            log.error(e.getMessage(), e);
543:                        }
544:                    }
545:                } catch (SQLException sqe) {
546:                    // log error, but return results.
547:                    log.error(sqe);
548:                }
549:                return results;
550:            }
551:
552:            // javadoc is inherited
553:            public int getSupportLevel(int feature, SearchQuery query)
554:                    throws SearchQueryException {
555:                int supportLevel;
556:                switch (feature) {
557:                case SearchQueryHandler.FEATURE_OFFSET:
558:                    // When sql handler does not support OFFSET, this query handler
559:                    // provides weak support by skipping resultsets.
560:                    // (falls through)
561:                case SearchQueryHandler.FEATURE_MAX_NUMBER:
562:                    // When sql handler does not support MAX NUMBER, this query
563:                    // handler provides weak support by truncating resultsets.
564:                    int handlerSupport = sqlHandler.getSupportLevel(feature,
565:                            query);
566:                    if (handlerSupport == SearchQueryHandler.SUPPORT_NONE) {
567:                        // TODO: implement weak support.
568:                        //supportLevel = SearchQueryHandler.SUPPORT_WEAK;
569:                        supportLevel = SearchQueryHandler.SUPPORT_NONE;
570:                    } else {
571:                        supportLevel = handlerSupport;
572:                    }
573:                    break;
574:
575:                default:
576:                    supportLevel = sqlHandler.getSupportLevel(feature, query);
577:                }
578:                return supportLevel;
579:            }
580:
581:            // javadoc is inherited
582:            public int getSupportLevel(Constraint constraint, SearchQuery query)
583:                    throws SearchQueryException {
584:                return sqlHandler.getSupportLevel(constraint, query);
585:            }
586:
587:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.