0001: /*-----------------------------------------------------------------------------
0002: * Enhydra Java Application Server
0003: * Copyright 1997-2000 Lutris Technologies, Inc.
0004: * All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions
0008: * are met:
0009: * 1. Redistributions of source code must retain the above copyright
0010: * notice, this list of conditions and the following disclaimer.
0011: * 2. Redistributions in binary form must reproduce the above copyright
0012: * notice, this list of conditions and the following disclaimer in
0013: * the documentation and/or other materials provided with the distribution.
0014: * 3. All advertising materials mentioning features or use of this software
0015: * must display the following acknowledgement:
0016: * This product includes Enhydra software developed by Lutris
0017: * Technologies, Inc. and its contributors.
0018: * 4. Neither the name of Lutris Technologies nor the names of its contributors
0019: * may be used to endorse or promote products derived from this software
0020: * without specific prior written permission.
0021: *
0022: * THIS SOFTWARE IS PROVIDED BY LUTRIS TECHNOLOGIES AND CONTRIBUTORS ``AS IS''
0023: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0024: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0025: * ARE DISCLAIMED. IN NO EVENT SHALL LUTRIS TECHNOLOGIES OR CONTRIBUTORS BE
0026: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0027: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0028: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0029: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0030: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0031: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0032: * POSSIBILITY OF SUCH DAMAGE.
0033: *-----------------------------------------------------------------------------
0034: * phoneList.data/PersonQuery.java
0035: *-----------------------------------------------------------------------------
0036: */
0037:
0038: package jspPhoneBook.data;
0039:
0040: import org.enhydra.dods.DODS;
0041: import com.lutris.dods.builder.generator.query.*;
0042: import com.lutris.appserver.server.sql.*;
0043: import org.enhydra.dods.cache.LRUCache;
0044: import org.enhydra.dods.cache.DataStructCache;
0045: import org.enhydra.dods.cache.QueryCache;
0046: import org.enhydra.dods.cache.QueryCacheItem;
0047: import org.enhydra.dods.cache.QueryResult;
0048: import org.enhydra.dods.cache.DataStructShell;
0049: import org.enhydra.dods.cache.DOShell;
0050: import org.enhydra.dods.cache.Condition;
0051: import org.enhydra.dods.statistics.Statistics;
0052: import org.enhydra.dods.cache.CacheConstants;
0053: import org.enhydra.dods.statistics.*;
0054: import com.lutris.logging.LogChannel;
0055: import com.lutris.logging.Logger;
0056: import com.lutris.appserver.server.sql.standard.StandardDBTransaction;
0057:
0058: import java.sql.*;
0059: import java.util.*;
0060: import java.math.*;
0061: import java.util.Date; // when I say Date, I don't mean java.sql.Date
0062:
0063: /**
0064: * PersonQuery is used to query the person table in the database.<BR>
0065: * It returns objects of type PersonDO.
0066: * <P>
0067: * General usage:
0068: * <P>
0069: * In DODS:
0070: * Create a Data Object named "Dog",
0071: * and create an Attribute named "Name",
0072: * and set that Attribute to "Can be queried."
0073: * DODS will then generate the method DogQuery.setQueryName().
0074: * <P>
0075: * In your Business Layer, prepare the query:<BR>
0076: * <P><PRE>
0077: * DogQuery dq = new DogQuery();
0078: * dq.setQueryName("Rex")
0079: * if ( Rex is a reserved name )
0080: * dq.requireUniqueInstance();
0081: * </PRE>
0082: * Then, get the query results one of two ways:
0083: * <P>
0084: * #1:<PRE>
0085: * String names = "";
0086: * DogDO[] dogs = dq.getDOArray();
0087: * for ( int i = 0; i < dogs.length; i++ ) {
0088: * names += dogs[i].getName() + " ";
0089: * }
0090: * </PRE>
0091: * or #2:<PRE>
0092: * String names = "";
0093: * DogDO dog;
0094: * while ( null != ( dog = dq.getNextDO() ) ) {
0095: * names += dog.getName() + " ";
0096: * }
0097: * </PRE>
0098: * <P>
0099: * Note: If <CODE>requireUniqueInstance()</CODE> was called,
0100: * then <CODE>getDOArray()</CODE> or <CODE>getNextDO()</CODE>
0101: * will throw an exception if more than one "Rex" was found.
0102: * <P>
0103: * Note: Results of the query will come from the Data Object cache if:
0104: * - The cache is available.
0105: * - Matches were found in the cache.
0106: * - No other tables (Data Objects of other types) were involved
0107: * in the query.
0108: * This can happen if you extend the <CODE>DogQuery</CODE> class
0109: * and you make calls to the <CODE>QueryBuilder</CODE> object
0110: * to add SQL involving other tables.
0111: * If any of these conditions is not true,
0112: * then any results from the query will come from the database.
0113: * <P>
0114: * To reuse the query object, call:
0115: * <P><PRE>
0116: * dq.reset();
0117: * </PRE>
0118: * @author EnhydraTeam
0119: * @version $Revision: 1.1 $
0120: */
0121: public class PersonQuery implements Query {
0122:
0123: private QueryBuilder builder;
0124:
0125: /**
0126: * logical name of the database for which PersonQuery object has been created
0127: */
0128: private String logicalDatabase;
0129:
0130: private ResultSet resultSet = null;
0131: private boolean uniqueInstance = false;
0132: private boolean loadData = false;
0133: private PersonDO[] DOs = null;
0134: private int arrayIndex = -1;
0135: private boolean needToRun = true;
0136: private LinkedHashMap cacheHits = null;
0137: private boolean isQueryByOId = false;
0138: private boolean hasNonOidCond = false;
0139: private boolean hitDb = false;
0140: private boolean userHitDb = false;
0141: private int maxDBrows = 0;
0142: private boolean orderRelevant = true; // true if order of query results is relavant, otherwise false
0143: private QueryCacheItem queryItem = null;
0144: private String currentHandle = null;
0145: private HashMap refs = new HashMap();
0146: private int iCurrentFetchSize = -1;
0147: private int iCurrentQueryTimeout = 0;
0148: private DBTransaction transaction = null;
0149:
0150: /**
0151: * Public constructor.
0152: *
0153:
0154: */
0155: public PersonQuery() {
0156:
0157: builder = new QueryBuilder("person", "person.*");
0158:
0159: String dbName = PersonDO.get_logicalDBName();
0160: try {
0161: String vendor = DODS.getDatabaseManager()
0162: .logicalDatabaseType(dbName);
0163: if (vendor != null) {
0164: builder.setDatabaseVendor(vendor);
0165: logicalDatabase = dbName;
0166: } else {
0167: builder.setDatabaseVendor();
0168: logicalDatabase = DODS.getDatabaseManager()
0169: .getDefaultDB();
0170: }
0171: } catch (Exception e) {
0172: builder.setDatabaseVendor();
0173: logicalDatabase = DODS.getDatabaseManager().getDefaultDB();
0174: }
0175: builder.setUserStringAppendWildcard(false);
0176: builder.setUserStringTrim(false);
0177: reset();
0178: }
0179:
0180: /**
0181: * Public constructor.
0182: *
0183: * @param dbTrans current database transaction
0184: */
0185: public PersonQuery(DBTransaction dbTrans) {
0186:
0187: builder = new QueryBuilder("person", "person.*");
0188:
0189: String dbName = null;
0190: if (dbTrans != null)
0191: dbName = dbTrans.getDatabaseName();
0192: else
0193: dbName = PersonDO.get_logicalDBName();
0194: try {
0195: transaction = dbTrans;
0196: String vendor = DODS.getDatabaseManager()
0197: .logicalDatabaseType(dbName);
0198: if (vendor != null) {
0199: builder.setDatabaseVendor(vendor);
0200: logicalDatabase = dbName;
0201: } else {
0202: builder.setDatabaseVendor();
0203: logicalDatabase = DODS.getDatabaseManager()
0204: .getDefaultDB();
0205: }
0206: } catch (Exception e) {
0207: builder.setDatabaseVendor();
0208: logicalDatabase = DODS.getDatabaseManager().getDefaultDB();
0209: }
0210: builder.setUserStringAppendWildcard(false);
0211: builder.setUserStringTrim(false);
0212: reset();
0213: }
0214:
0215: /**
0216: * Return logical name of the database that PersonQuery object uses
0217: *
0218: * @return param logical database name
0219: *
0220: */
0221: public String getLogicalDatabase() {
0222: return logicalDatabase;
0223: }
0224:
0225: /**
0226: * Change logical database to another logical database (which name is dbName)
0227: *
0228: * @param dbName the logical name of the database
0229: *
0230: */
0231: public void setLogicalDatabase(String dbName) throws SQLException,
0232: DatabaseManagerException {
0233: String vendor = DODS.getDatabaseManager().logicalDatabaseType(
0234: dbName);
0235: if (vendor != null) {
0236: builder.setDatabaseVendor(vendor);
0237: logicalDatabase = dbName;
0238: } else {
0239: builder.setDatabaseVendor();
0240: logicalDatabase = DODS.getDatabaseManager().getDefaultDB();
0241: }
0242: reset();
0243: }
0244:
0245: // WebDocWf extension for unique query results without SQL DISTINCT
0246: // The following lines has been added:
0247: private boolean unique = false;
0248:
0249: /**
0250: * Set the unique flag of the query
0251: *
0252: * @param newUnique The unique flag for the query
0253: *
0254: * WebDocWf extension
0255: *
0256: */
0257: public void setUnique(boolean newUnique) {
0258: unique = newUnique;
0259: }
0260:
0261: /**
0262: * Get the unique flag of the query
0263: *
0264: * @return The unique flag of the query
0265: *
0266: * WebDocWf extension
0267: *
0268: */
0269: public boolean getUnique() {
0270: return unique;
0271: }
0272:
0273: // WebDocWf extension for skipping the n first rows of the result
0274: // The following lines has been added:
0275: private int readSkip = 0;
0276:
0277: /**
0278: * Set the readSkip number of the query
0279: *
0280: * @param newreadSkip The number of results to skip
0281: *
0282: * WebDocWf extension
0283: *
0284: */
0285: public void setReadSkip(int newReadSkip) {
0286: readSkip = newReadSkip;
0287: }
0288:
0289: /**
0290: * Get the readSkip number of the query
0291: *
0292: * @return The number of rows which are skipped
0293: *
0294: * WebDocWf extension
0295: *
0296: */
0297: public int getReadSkip() {
0298: return readSkip;
0299: }
0300:
0301: // WebDocWf extension for select rowcount limit
0302: // The following lines has been added:
0303: private int databaseLimit = 0;
0304:
0305: /**
0306: * Set the database limit of the query
0307: *
0308: * @param newLimit The limit for the query
0309: *
0310: * WebDocWf extension
0311: *
0312: */
0313: public void setDatabaseLimit(int newLimit) {
0314: databaseLimit = newLimit;
0315: }
0316:
0317: /**
0318: * Get the database limit of the query
0319: *
0320: * @return The database limit of the query
0321: *
0322: * WebDocWf extension
0323: *
0324: */
0325: public int getDatabaseLimit() {
0326: return databaseLimit;
0327: }
0328:
0329: private boolean databaseLimitExceeded = false;
0330:
0331: /**
0332: * Get the database limit exceeded flag of the query.
0333: *
0334: * @return The database limit exceeded flag of the query
0335: * True if there would have been more rows than the limit, otherwise false.
0336: *
0337: * WebDocWf extension
0338: */
0339: public boolean getDatabaseLimitExceeded() {
0340: return databaseLimitExceeded;
0341: }
0342:
0343: // end of WebDocWf extension for select rowcount limit
0344:
0345: /**
0346: * Set that all queries go to database, not to cache.
0347: */
0348: public void hitDatabase() {
0349: userHitDb = true;
0350: }
0351:
0352: // WebDocWf extension for extended wildcard support
0353: // The following rows have been added:
0354:
0355: /**
0356: * Set user string wildcard.
0357: *
0358: * @param newUserStringWildcard New user string wildcard.
0359: *
0360: * WebDocWf extension
0361: */
0362: public void setUserStringWildcard(String newUserStringWildcard) {
0363: builder.setUserStringWildcard(newUserStringWildcard);
0364: }
0365:
0366: /**
0367: * Set user string single wildcard.
0368: *
0369: * @param newUserStringSingleWildcard New user string single wildcard.
0370: *
0371: * WebDocWf extension
0372: */
0373: public void setUserStringSingleWildcard(
0374: String newUserStringSingleWildcard) {
0375: builder
0376: .setUserStringSingleWildcard(newUserStringSingleWildcard);
0377: }
0378:
0379: /**
0380: * Set user string single wildcard escape.
0381: *
0382: * @param newUserStringSingleWildcardEscape New user string single wildcard escape.
0383: *
0384: * WebDocWf extension
0385: */
0386: public void setUserStringSingleWildcardEscape(
0387: String newUserStringSingleWildcardEscape) {
0388: builder
0389: .setUserStringSingleWildcardEscape(newUserStringSingleWildcardEscape);
0390: }
0391:
0392: /**
0393: * Set user string wildcard escape.
0394: *
0395: * @param newUserStringWildcardEscape New user string wildcard escape.
0396: *
0397: * WebDocWf extension
0398: */
0399: public void setUserStringWildcardEscape(
0400: String newUserStringWildcardEscape) {
0401: builder
0402: .setUserStringWildcardEscape(newUserStringWildcardEscape);
0403: }
0404:
0405: /**
0406: * Set user string append wildcard.
0407: *
0408: * @param userStringAppendWildcard New user string append wildcard.
0409: *
0410: * WebDocWf extension
0411: */
0412: public void setUserStringAppendWildcard(
0413: boolean userStringAppendWildcard) {
0414: builder.setUserStringAppendWildcard(userStringAppendWildcard);
0415: }
0416:
0417: /**
0418: * Set user string trim.
0419: *
0420: * @param userStringTrim New user string trim.
0421: *
0422: * WebDocWf extension
0423: */
0424: public void setUserStringTrim(boolean userStringTrim) {
0425: builder.setUserStringTrim(userStringTrim);
0426: }
0427:
0428: /**
0429: * Get user string wildcard.
0430: *
0431: * @return User string wildcard.
0432: *
0433: * WebDocWf extension
0434: */
0435: public String getUserStringWildcard() {
0436: return builder.getUserStringWildcard();
0437: }
0438:
0439: /**
0440: * Get user string single wildcard.
0441: *
0442: * @return User string single wildcard.
0443: *
0444: * WebDocWf extension
0445: */
0446: public String getUserStringSingleWildcard() {
0447: return builder.getUserStringSingleWildcard();
0448: }
0449:
0450: /**
0451: * Get user string single wildcard escape.
0452: *
0453: * @return User string single wildcard escape.
0454: *
0455: * WebDocWf extension
0456: */
0457: public String getUserStringSingleWildcardEscape() {
0458: return builder.getUserStringSingleWildcardEscape();
0459: }
0460:
0461: /**
0462: * Get user string wildcard escape.
0463: *
0464: * @return User string wildcard escape.
0465: *
0466: * WebDocWf extension
0467: */
0468: public String getUserStringWildcardEscape() {
0469: return builder.getUserStringWildcardEscape();
0470: }
0471:
0472: /**
0473: * Get user string append wildcard.
0474: *
0475: * @return User string append wildcard.
0476: *
0477: * WebDocWf extension
0478: */
0479: public boolean getUserStringAppendWildcard() {
0480: return builder.getUserStringAppendWildcard();
0481: }
0482:
0483: /**
0484: * Get user string trim.
0485: *
0486: * @return User string trim.
0487: *
0488: * WebDocWf extension
0489: */
0490: public boolean getUserStringTrim() {
0491: return builder.getUserStringTrim();
0492: }
0493:
0494: // end of WebDocWf extension for extended wildcard support
0495:
0496: /**
0497: * Perform the query on the database, and prepare the
0498: * array of returned DO objects.
0499: *
0500: * @exception DataObjectException If a database access error occurs.
0501: * @exception NonUniqueQueryException If too many rows were found.
0502: */
0503: private void getQueryByOIds(Vector DOs) throws DataObjectException {
0504: if (DOs.size() == 0)
0505: return;
0506: PersonDO DO = null;
0507: DOShell shell = null;
0508: PersonQuery tmpQuery = null;
0509: Date startQueryTime = new Date();
0510: long queryTime = 0;
0511: for (int i = 0; i < DOs.size(); i++) {
0512: shell = (DOShell) DOs.elementAt(i);
0513: tmpQuery = new PersonQuery(transaction);
0514: try {
0515: tmpQuery.setQueryHandle(shell.handle);
0516: tmpQuery.requireUniqueInstance();
0517:
0518: DO = tmpQuery.getNextDO();
0519: if (null == DO)
0520: throw new DataObjectException(
0521: "PersonDO DO not found for id="
0522: + shell.handle);
0523: } catch (Exception e) {
0524: throw new DataObjectException("Duplicate ObjectId");
0525: }
0526: shell.dataObject = DO;
0527: }
0528: Date stopQueryTime = new Date();
0529: queryTime = stopQueryTime.getTime() - startQueryTime.getTime();
0530: PersonDO.statistics.updateQueryByOIdAverageTime((new Long(
0531: queryTime)).intValue(), DOs.size());
0532: }
0533:
0534: /**
0535: * Perform the query on the database, and prepare the
0536: * array of returned DO objects.
0537: *
0538: * @exception DataObjectException If a database access error occurs.
0539: * @exception NonUniqueQueryException If too many rows were found.
0540: */
0541: private void runQuery() throws DataObjectException,
0542: NonUniqueQueryException {
0543: needToRun = false;
0544: arrayIndex = -1;
0545: DBQuery dbQuery = null;
0546: Date startQueryTime = new Date();
0547: long queryTime = 0;
0548: boolean readDOs = false;
0549: boolean canUseQueryCache = true;
0550: CacheStatistics stat = null;
0551: boolean resultsFromQCache = false;
0552: QueryCacheItem queryCachedItem = null;
0553:
0554: if ((transaction != null)
0555: && (transaction instanceof com.lutris.appserver.server.sql.standard.StandardDBTransaction)) {
0556: if (((com.lutris.appserver.server.sql.standard.StandardDBTransaction) transaction)
0557: .getAutoWrite())
0558: try {
0559: transaction.write();
0560: } catch (SQLException sqle) {
0561: sqle.printStackTrace();
0562: throw new DataObjectException(
0563: "Couldn't write transaction: " + sqle);
0564: }
0565: ((com.lutris.appserver.server.sql.standard.StandardDBTransaction) transaction)
0566: .dontAggregateDOModifications();
0567: }
0568:
0569: try {
0570: QueryResult results = null;
0571: DOShell shell = null;
0572: if (isQueryByOId && !hasNonOidCond) { // query by OId
0573: results = new QueryResult();
0574: if (currentHandle != null) {
0575: if (transaction != null
0576: && _tr_(transaction).getTransactionCache() != null
0577: && !loadData) {
0578: PersonDO DO = (PersonDO) _tr_(transaction)
0579: .getTransactionCache().getDOByHandle(
0580: currentHandle);
0581: if (DO != null) {
0582: shell = new DOShell(DO);
0583: results.DOs.add(shell);
0584: resultsFromQCache = true;
0585: } else
0586: resultsFromQCache = false;
0587: }
0588: if (!resultsFromQCache) { // DO isn't found in the transaction cache
0589: PersonDataStruct DS = (PersonDataStruct) PersonDO.cache
0590: .getDataStructByHandle(currentHandle);
0591: if (DS != null) { // DO is found in the cache
0592: PersonDO DO = (PersonDO) PersonDO
0593: .createExisting(DS.get_OId(),
0594: transaction);
0595: shell = new DOShell(DO);
0596: results.DOs.add(shell);
0597: resultsFromQCache = true;
0598: } else { // DO isn't found in the cache
0599: if (PersonDO.cache.isFull())
0600: resultsFromQCache = false;
0601: }
0602: }
0603: }//currentHandle != null
0604: } else { // other queries
0605: if ((PersonDO.cache.isFull()) && (!hitDb)) {
0606: resultsFromQCache = true;
0607: } else {
0608: if (PersonDO.cache.getLevelOfCaching() == CacheConstants.QUERY_CACHING) {
0609: if (hitDb) { // statistics about complex query
0610: stat = null;
0611: stat = PersonDO.statistics
0612: .getCacheStatistics(CacheConstants.COMPLEX_QUERY_CACHE);
0613: if (stat != null) {
0614: stat.incrementCacheAccessNum(1);
0615: }
0616: } else { // statistics about simple query
0617: stat = null;
0618: stat = PersonDO.statistics
0619: .getCacheStatistics(CacheConstants.SIMPLE_QUERY_CACHE);
0620: if (stat != null) {
0621: stat.incrementCacheAccessNum(1);
0622: }
0623: }
0624: }
0625: if (transaction != null)
0626: canUseQueryCache = !transaction
0627: .preventCacheQueries();
0628: if ((PersonDO.cache.getLevelOfCaching() == CacheConstants.QUERY_CACHING)
0629: && canUseQueryCache) {
0630: String queryID = builder.getSQLwithParms(); //unique representation of query
0631: int resNum = 0;
0632: int evaluateNo = 0;
0633: if (hitDb)
0634: queryCachedItem = ((QueryCache) PersonDO.cache)
0635: .getComplexQueryCacheItem(
0636: logicalDatabase, queryID);
0637: else
0638: queryCachedItem = ((QueryCache) PersonDO.cache)
0639: .getSimpleQueryCacheItem(
0640: logicalDatabase, queryID);
0641: queryItem.setQueryId(queryID); // queryItem defined as private template attribute
0642: if (queryCachedItem == null) { // query doesn't exist
0643: if ((!builder.isMultiTableJoin())
0644: || PersonDO.isAllReadOnly()) {
0645: if (hitDb)
0646: ((QueryCache) PersonDO.cache)
0647: .addComplexQuery(queryItem); // register complex query
0648: else
0649: ((QueryCache) PersonDO.cache)
0650: .addSimpleQuery(queryItem); // register simple query
0651: }
0652: } else { // query found
0653: if (!(isOrderRelevant() && queryCachedItem
0654: .isModifiedQuery())) {
0655: if (hitDb) { // statistics about complex cache
0656: stat = null;
0657: stat = PersonDO.statistics
0658: .getCacheStatistics(CacheConstants.COMPLEX_QUERY_CACHE);
0659: if (stat != null) {
0660: stat.incrementCacheHitsNum(1);
0661: }
0662: } else { // statistics about simple cache
0663: stat = null;
0664: stat = PersonDO.statistics
0665: .getCacheStatistics(CacheConstants.SIMPLE_QUERY_CACHE);
0666: if (stat != null) {
0667: stat.incrementCacheHitsNum(1);
0668: }
0669: }
0670:
0671: int limitOfRes;
0672: if (databaseLimit == 0)
0673: limitOfRes = 0;
0674: else
0675: limitOfRes = readSkip
0676: + databaseLimit + 1;
0677: if (!unique) {
0678: if (hitDb)
0679: results = ((QueryCache) PersonDO.cache)
0680: .getComplexQueryResults(
0681: logicalDatabase,
0682: queryID,
0683: limitOfRes,
0684: maxDBrows);
0685: else
0686: results = ((QueryCache) PersonDO.cache)
0687: .getSimpleQueryResults(
0688: logicalDatabase,
0689: queryID,
0690: limitOfRes,
0691: maxDBrows);
0692: } else { // (! unique)
0693: if (hitDb)
0694: results = ((QueryCache) PersonDO.cache)
0695: .getComplexQueryResults(
0696: logicalDatabase,
0697: queryID,
0698: limitOfRes,
0699: maxDBrows, true);
0700: else
0701: results = ((QueryCache) PersonDO.cache)
0702: .getSimpleQueryResults(
0703: logicalDatabase,
0704: queryID,
0705: limitOfRes,
0706: maxDBrows, true);
0707: } // (! unique)
0708: if (results != null) {
0709: //sinisa 06.08.2003.
0710: results = getCachedResults(results);
0711: resNum = results.DOs.size();
0712: if (databaseLimit != 0) { // databaseLimitExceeded begin
0713: if (resNum == readSkip
0714: + databaseLimit + 1) {
0715: resNum--;
0716: databaseLimitExceeded = true;
0717: results.DOs.remove(readSkip
0718: + databaseLimit);
0719: } else {
0720: if ((resNum == readSkip
0721: + databaseLimit)
0722: && (!queryCachedItem
0723: .isCompleteResult()))
0724: databaseLimitExceeded = true;
0725: }
0726: } // databaseLimitExceeded end
0727: if ((databaseLimit != 0 && (resNum == (readSkip + databaseLimit)))
0728: || (maxDBrows != 0 && (resNum + results.skippedUnique) == maxDBrows)
0729: || (queryCachedItem
0730: .isCompleteResult())) {
0731: int lazyTime = PersonDO.statistics
0732: .getQueryByOIdAverageTime()
0733: * results.lazy.size();
0734: if (lazyTime <= queryCachedItem
0735: .getTime()) {
0736: resultsFromQCache = true;
0737: getQueryByOIds(results.lazy); // gets cached query results from database
0738: } else
0739: databaseLimitExceeded = false;
0740: } else
0741: databaseLimitExceeded = false;
0742: } // (results != null)
0743:
0744: } // !(isOrderRelevant() && queryCachedItem.isModifiedQuery())
0745: } // query found
0746: } // if QUERY_CACHING
0747: } // full caching
0748: } // other queries
0749: if ((userHitDb) || (!resultsFromQCache)) { // go to database
0750:
0751: dbQuery = PersonDO.createQuery(transaction);
0752:
0753: results = new QueryResult();
0754: int resultCount = 0;
0755: boolean bHasMoreResults = false;
0756: if (((PersonDO.getConfigurationAdministration()
0757: .getTableConfiguration().isLazyLoading()) || isCaching())
0758: && (!builder.getPreventPrimaryKeySelect())
0759: && !loadData) {
0760: builder.resetSelectedFields();
0761: builder.setSelectClause("person."
0762: + PersonDO.get_OIdColumnName()
0763: + ", person."
0764: + PersonDO.get_versionColumnName());
0765: } else
0766: builder.setSelectClause("person.*");
0767: dbQuery.query(this ); // invokes executeQuery
0768:
0769: if (!unique) {
0770: while ((bHasMoreResults = resultSet.next())
0771: && (databaseLimit == 0 || (results.DOs
0772: .size() < databaseLimit))) {
0773: PersonDO newDO;
0774: PersonDataStruct newDS;
0775:
0776: if (((PersonDO.getConfigurationAdministration()
0777: .getTableConfiguration()
0778: .isLazyLoading()) || isCaching())
0779: && (!builder
0780: .getPreventPrimaryKeySelect())
0781: && !loadData) {
0782: newDO = PersonDO
0783: .createExisting(
0784: new ObjectId(
0785: resultSet
0786: .getBigDecimal(CoreDO
0787: .get_OIdColumnName())),
0788: refs, transaction);
0789: newDO.set_Version(resultSet.getInt(PersonDO
0790: .get_versionColumnName()));
0791: } else
0792: newDO = PersonDO.createExisting(resultSet,
0793: refs, transaction);
0794: if (transaction == null) {
0795: if (newDO != null
0796: && newDO.isTransactionCheck()) {
0797: String trace = "";
0798: StackTraceElement[] traceElements = (new Throwable())
0799: .getStackTrace();
0800: for (int i = 0; i < traceElements.length; i++)
0801: trace += traceElements[i]
0802: .toString()
0803: + "\n";
0804: DODS
0805: .getLogChannel()
0806: .write(
0807: Logger.WARNING,
0808: "DO without transaction context is created : Database: "
0809: + newDO
0810: .get_OriginDatabase()
0811: + " PersonDO class, oid: "
0812: + newDO
0813: .get_OId()
0814: + ", version: "
0815: + newDO
0816: .get_Version()
0817: + " \n" + trace);
0818: }
0819: }
0820:
0821: if (queryItem != null) {
0822: queryItem.add((PersonDataStruct) newDO
0823: .originalData_get());
0824: }
0825: if (((PersonDO.getConfigurationAdministration()
0826: .getTableConfiguration()
0827: .isLazyLoading()) || isCaching())
0828: && (!builder
0829: .getPreventPrimaryKeySelect())
0830: && !loadData) {
0831: } else
0832: newDS = PersonDO
0833: .addToCache((PersonDataStruct) newDO
0834: .originalData_get());
0835:
0836: if (resultCount >= readSkip) {
0837: shell = new DOShell(newDO);
0838: results.DOs.add(shell);
0839: }
0840: resultCount++;
0841:
0842: } // while
0843: } // (!unique)
0844:
0845: else { // (! unique)
0846: HashSet hsResult = new HashSet(readSkip
0847: + databaseLimit);
0848: while ((bHasMoreResults = resultSet.next())
0849: && (databaseLimit == 0 || (results.DOs
0850: .size() < databaseLimit))) {
0851: PersonDO newDO;
0852: PersonDataStruct newDS;
0853:
0854: if (((PersonDO.getConfigurationAdministration()
0855: .getTableConfiguration()
0856: .isLazyLoading()) || isCaching())
0857: && (!builder
0858: .getPreventPrimaryKeySelect())
0859: && !loadData) {
0860: newDO = PersonDO
0861: .createExisting(
0862: new ObjectId(
0863: resultSet
0864: .getBigDecimal(CoreDO
0865: .get_OIdColumnName())),
0866: refs, transaction);
0867: newDO.set_Version(resultSet.getInt(PersonDO
0868: .get_versionColumnName()));
0869: } else
0870: newDO = PersonDO.createExisting(resultSet,
0871: refs, transaction);
0872: if (transaction == null) {
0873: if (newDO != null
0874: && newDO.isTransactionCheck()) {
0875: String trace = "";
0876: StackTraceElement[] traceElements = (new Throwable())
0877: .getStackTrace();
0878: for (int i = 0; i < traceElements.length; i++)
0879: trace += traceElements[i]
0880: .toString()
0881: + "\n";
0882: DODS
0883: .getLogChannel()
0884: .write(
0885: Logger.WARNING,
0886: "DO without transaction context is created : Database: "
0887: + newDO
0888: .get_OriginDatabase()
0889: + " PersonDO class, oid: "
0890: + newDO
0891: .get_OId()
0892: + ", version: "
0893: + newDO
0894: .get_Version()
0895: + " \n" + trace);
0896: }
0897: }
0898:
0899: if (queryItem != null) {
0900: queryItem.add((PersonDataStruct) newDO
0901: .originalData_get());
0902: }
0903: if (((PersonDO.getConfigurationAdministration()
0904: .getTableConfiguration()
0905: .isLazyLoading()) || isCaching())
0906: && (!builder
0907: .getPreventPrimaryKeySelect())
0908: && !loadData) {
0909: } else
0910: newDS = PersonDO
0911: .addToCache((PersonDataStruct) newDO
0912: .originalData_get());
0913:
0914: if (!hsResult.contains(newDO.get_Handle())) {
0915: hsResult.add(newDO.get_Handle());
0916: if (resultCount >= readSkip) {
0917:
0918: shell = new DOShell(newDO);
0919: results.DOs.add(shell);
0920: }
0921: resultCount++;
0922: }
0923:
0924: } // while
0925: } // else (! unique)
0926:
0927: if ((results.DOs.size() == databaseLimit)
0928: && bHasMoreResults) {
0929: resultSet.close();
0930: databaseLimitExceeded = true;
0931: }
0932: if (maxDBrows > 0) {
0933: if (!bHasMoreResults) {
0934: if ((databaseLimit > 0)
0935: && databaseLimit < maxDBrows)
0936: queryItem.setCompleteResult(true);
0937: }
0938: } else {
0939: if (!bHasMoreResults)
0940: queryItem.setCompleteResult(true);
0941: }
0942: Date stopQueryTime = new Date();
0943: queryTime = stopQueryTime.getTime()
0944: - startQueryTime.getTime();
0945: if (queryItem != null) {
0946: queryItem.setTime((new Long(queryTime)).intValue());
0947: if (queryCachedItem != null) {
0948: if (queryItem.isCompleteResult()
0949: || (queryCachedItem.isModifiedQuery() && isOrderRelevant())
0950: || (queryCachedItem.getResultNum() < queryItem
0951: .getResultNum())) {
0952: if ((!builder.isMultiTableJoin())
0953: || PersonDO.isAllReadOnly()) {
0954: if (hitDb) {
0955: ((QueryCache) PersonDO.cache)
0956: .addComplexQuery(queryItem);
0957: } else {
0958: ((QueryCache) PersonDO.cache)
0959: .addSimpleQuery(queryItem);
0960: }
0961: } // !builder.isMultiTableJoin()
0962:
0963: } else {
0964: if ((queryCachedItem.getResultNum() < (readSkip + databaseLimit))
0965: && (queryCachedItem.getResultNum() < maxDBrows)) {
0966: queryCachedItem.setCompleteResult(true);
0967: }
0968: }
0969: if ((queryItem.getResultNum() < (readSkip + databaseLimit))
0970: && (queryItem.getResultNum() < maxDBrows))
0971: queryItem.setCompleteResult(true);
0972: } // (queryCachedItem != null)
0973: } // (queryItem != null)
0974: int maxExecuteTime = PersonDO.cache
0975: .getTableConfiguration().getMaxExecuteTime();
0976: if (maxExecuteTime > 0 && queryTime > maxExecuteTime)
0977: DODS.getLogChannel().write(
0978: Logger.WARNING,
0979: "sql = " + builder.getSQLwithParms()
0980: + " execute time = " + queryTime
0981: + "max table execute time = "
0982: + maxExecuteTime);
0983: } else { // ( userHitDb) || (!resultsFromQCache)
0984: if (PersonDO.cache.isFull() && (!hitDb)) {
0985: results = new QueryResult();
0986: if (readSkip < cacheHits.size()) {
0987: Vector vect = new Vector(cacheHits.values());
0988: results.DOs = new Vector();
0989: PersonDO DO = null;
0990: PersonDataStruct DS = null;
0991: String cachePrefix = getLogicalDatabase() + ".";
0992: int i = readSkip;
0993: while (i < vect.size()
0994: && ((databaseLimit == 0) || (i <= readSkip
0995: + databaseLimit))) {
0996: boolean findInTransactionCache = false;
0997: DS = (PersonDataStruct) vect.get(i);
0998: if (transaction != null
0999: && _tr_(transaction)
1000: .getTransactionCache() != null
1001: && !loadData) {
1002: DO = (PersonDO) _tr_(transaction)
1003: .getTransactionCache()
1004: .getDOByHandle(
1005: cachePrefix
1006: + DS
1007: .get_OId()
1008: .toString());
1009: if (DO != null)
1010: findInTransactionCache = true;
1011: }
1012: if (!findInTransactionCache) {
1013: DO = (PersonDO) PersonDO
1014: .createExisting(DS.get_OId(),
1015: transaction);
1016: }
1017:
1018: results.DOs.add(DO);
1019:
1020: i++;
1021: }
1022: readDOs = true;
1023: }
1024:
1025: if ((databaseLimit != 0)
1026: && (results.DOs.size() == databaseLimit + 1)) {
1027: databaseLimitExceeded = true;
1028: results.DOs.remove(databaseLimit);
1029: }
1030:
1031: } //if full
1032:
1033: } // ( userHitDb) || (!resultsFromQCache)
1034: // end of WebDocWf extension
1035: if (results.DOs.size() > 1 && uniqueInstance)
1036: throw new NonUniqueQueryException(
1037: "Too many rows returned from database");
1038: DOs = new PersonDO[results.DOs.size()];
1039: PersonDataStruct orig;
1040: if (readDOs) {
1041: for (int i = 0; i < results.DOs.size(); i++) {
1042: DOs[i] = (PersonDO) results.DOs.elementAt(i);
1043: }
1044: } else {
1045: for (int i = 0; i < results.DOs.size(); i++) {
1046: DOs[i] = (PersonDO) ((DOShell) results.DOs
1047: .elementAt(i)).dataObject;
1048: }
1049: }
1050: arrayIndex = 0;
1051: if (isQueryByOId && !hasNonOidCond) {
1052: PersonDO.statistics.incrementQueryByOIdNum();
1053: PersonDO.statistics.updateQueryByOIdAverageTime(
1054: (new Long(queryTime)).intValue(), 1);
1055: } else {
1056: PersonDO.statistics.incrementQueryNum();
1057: PersonDO.statistics.updateQueryAverageTime((new Long(
1058: queryTime)).intValue());
1059: }
1060: } catch (SQLException se) {
1061: if (null == se.getSQLState()) {
1062: throw new DataObjectException("Unknown SQLException",
1063: se);
1064: }
1065: if (se.getSQLState().startsWith("02")
1066: && se.getErrorCode() == 100) {
1067: throw new DataObjectException(
1068: "Update or delete DO is out of synch", se);
1069: } else if (se.getSQLState().equals("S1000")
1070: && se.getErrorCode() == -268) {
1071: throw new DataObjectException(
1072: "Integrity constraint violation", se);
1073: } else {
1074: throw new DataObjectException("Data Object Error", se);
1075: }
1076: } catch (ObjectIdException oe) {
1077: throw new DataObjectException("Object ID Error", oe);
1078: } catch (DatabaseManagerException de) {
1079: throw new DataObjectException("Database connection Error",
1080: de);
1081: } finally {
1082: if ((null != dbQuery) && (null == transaction))
1083: dbQuery.release();
1084: }
1085: }
1086:
1087: /**
1088: * Limit the number of rows (DOs) returned.
1089: * NOTE: When setting a limit on rows returned by a query,
1090: * you usually want to use a call to an addOrderBy method
1091: * to cause the most interesting rows to be returned first.
1092:
1093: * However, the DO cache does not yet support the Order By operation.
1094: * Using the addOrderBy method forces the query to hit the database.
1095: * So, setMaxRows also forces the query to hit the database.
1096:
1097: *
1098: * @param maxRows Max number of rows (DOs) returned.
1099: *
1100: * @exception DataObjectException If a database access error occurs.
1101: * @exception NonUniqueQueryException If too many rows were found.
1102: */
1103: public void setMaxRows(int maxRows) throws DataObjectException,
1104: NonUniqueQueryException {
1105:
1106: maxDBrows = maxRows;
1107: builder.setMaxRows(maxRows);
1108: }
1109:
1110: /**
1111: * Return limit of rows (DOs) returned.
1112: * @return Max number of rows (DOs) returned.
1113: *
1114: */
1115: public int getMaxRows() {
1116: return maxDBrows;
1117: }
1118:
1119: /**
1120: * Returns attribute orderRelevant.
1121: *
1122: * @return true if order of query results is relavant, otherwise false.
1123: */
1124: public boolean isOrderRelevant() {
1125: return orderRelevant;
1126: }
1127:
1128: /**
1129: * Sets attribute orderRelevant.
1130: *
1131: * @param newOrderRelavant new value of attribute orderRelavant.
1132: */
1133: public void setOrderRelevant(boolean newOrderRelevant) {
1134: orderRelevant = newOrderRelevant;
1135: }
1136:
1137: /**
1138: * Return QueryResult with read DOs or DataStructs from caches.
1139: *
1140: * @return QueryResult .
1141: *
1142: * @exception DataObjectException If a database access error occurs.
1143: */
1144: public QueryResult getCachedResults(QueryResult result)
1145: throws DataObjectException {
1146: Vector tempVec = result.DOs;
1147: if (tempVec == null)
1148: return null;
1149: result.DOs = new Vector();
1150: result.lazy = new Vector();
1151: DOShell shell = null;
1152: PersonDO cacheDO = null;
1153: PersonDataStruct cacheDS = null;
1154: String handle = "";
1155: String cachePrefix = getLogicalDatabase() + ".";
1156:
1157: for (int i = 0; i < tempVec.size(); i++) {
1158:
1159: if (tempVec.get(i) != null) {
1160: cacheDO = null;
1161: cacheDS = null;
1162: handle = (String) tempVec.get(i);
1163: shell = new DOShell(handle);
1164: if (transaction != null
1165: && _tr_(transaction).getTransactionCache() != null
1166: && !loadData) {
1167: try {
1168: cacheDO = (PersonDO) _tr_(transaction)
1169: .getTransactionCache().getDOByHandle(
1170: cachePrefix + handle);
1171: } catch (Exception e) {
1172: }
1173: }
1174: if (cacheDO == null) {
1175: cacheDS = (PersonDataStruct) PersonDO.cache
1176: .getDataStructByHandle(cachePrefix + handle);
1177: if (cacheDS != null) {
1178: try {
1179: cacheDO = (PersonDO) PersonDO
1180: .createExisting(cacheDS.get_OId(),
1181: transaction);
1182: } catch (Exception e) {
1183: }
1184: }
1185: }
1186: if (cacheDO == null) {
1187: result.lazy.add(shell);
1188: } else {
1189: shell.dataObject = cacheDO;
1190: }
1191: result.DOs.add(shell);
1192: }
1193: } //for
1194: return result;
1195: }
1196:
1197: /**
1198: * Return array of DOs constructed from ResultSet returned by query.
1199: *
1200: * @return Array of DOs constructed from ResultSet returned by query.
1201: *
1202: * @exception DataObjectException If a database access error occurs.
1203: * @exception NonUniqueQueryException If too many rows were found.
1204: */
1205: public PersonDO[] getDOArray() throws DataObjectException,
1206: NonUniqueQueryException {
1207: if (needToRun)
1208: runQuery();
1209: return DOs;
1210: }
1211:
1212: /**
1213: * Return successive DOs from array built from ResultSet returned by query.
1214: *
1215: * @return DOs from array built from ResultSet returned by query.
1216: *
1217: * @exception DataObjectException If a database access error occurs.
1218: * @exception NonUniqueQueryException If too many rows were found.
1219: */
1220: public PersonDO getNextDO() throws DataObjectException,
1221: NonUniqueQueryException {
1222: if (needToRun)
1223: runQuery();
1224: if (null == DOs) {
1225: /* This should never happen.
1226: * runQuery() should either throw an exception
1227: * or create an array of DOs, possibly of zero length.
1228: */
1229: return null;
1230: }
1231: if (arrayIndex < DOs.length)
1232: return DOs[arrayIndex++];
1233: return null;
1234: }
1235:
1236: /**
1237: * Set the OID to query.
1238: * WARNING! This method assumes that table <CODE>person</CODE>
1239: * has a column named <CODE>"oid"</CODE>.
1240: * This method is called from the DO classes to retrieve an object by id.
1241: *
1242: * @param oid The object id to query.
1243: */
1244: public void setQueryOId(ObjectId oid) {
1245: // Remove from cacheHits any DO that does not meet this
1246: // setQuery requirement.
1247: String handle = getLogicalDatabase() + "." + oid.toString();
1248: if (PersonDO.cache.isFull()) {
1249: PersonDataStruct DS = (PersonDataStruct) cacheHits
1250: .get(handle);
1251: cacheHits = new LinkedHashMap();
1252: if (DS != null) {
1253: cacheHits.put(handle, DS);
1254: }
1255: }
1256: if (isQueryByOId) { // query by OId already has been invoked
1257:
1258: hasNonOidCond = true; // this is not simple query by oid: has at least two conditions for oids
1259:
1260: } else { // (isQueryByOid)
1261: currentHandle = handle;
1262: }
1263: isQueryByOId = true;
1264: try {
1265: Condition cond = new Condition(PersonDataStruct.COLUMN_OID,
1266: handle, "=");
1267: queryItem.addCond(cond);
1268: } catch (Exception e) {
1269: }
1270: // Also prepare the SQL needed to query the database
1271: // in case there is no cache, or the query involves other tables.
1272: builder.addWhere(PersonDO.PrimaryKey, oid.toBigDecimal(),
1273: QueryBuilder.EQUAL);
1274: }
1275:
1276: /**
1277: * Set the object handle to query.
1278: * This is a variant of setQueryOId().
1279: *
1280: * @param handle The string version of the id to query.
1281: */
1282: public void setQueryHandle(String handle) throws ObjectIdException {
1283: ObjectId oid = new ObjectId(handle);
1284: setQueryOId(oid);
1285: }
1286:
1287: /**
1288: * Set "unique instance" assertion bit.
1289: * The first call to the next() method will throw an exception
1290: * if more than one object was found.
1291: */
1292: public void requireUniqueInstance() {
1293: uniqueInstance = true;
1294: }
1295:
1296: /**
1297: * Set loadData parameter. if parameter is set to true, Query select t.* is performed.
1298: * @param newValue boolean (true/false)
1299: */
1300: public void setLoadData(boolean newValue) {
1301: loadData = newValue;
1302: }
1303:
1304: /**
1305: * Return true if Query is prepared for select t1.* statement. Otherwise return false.
1306: * @return boolean (true/false)
1307: */
1308: public boolean getLoadData() {
1309: if (loadData)
1310: return true;
1311: else
1312: return ((PersonDO.getConfigurationAdministration()
1313: .getTableConfiguration().isLazyLoading()) || isCaching());
1314: }
1315:
1316: /**
1317: * Reset the query parameters.
1318: */
1319: public void reset() {
1320: if (PersonDO.cache.isFull()) {
1321: cacheHits = new LinkedHashMap(PersonDO.cache
1322: .getCacheContent());
1323: }
1324: DOs = null;
1325: uniqueInstance = false;
1326: needToRun = true;
1327: isQueryByOId = false;
1328: hasNonOidCond = false;
1329: loadData = false;
1330: builder.reset();
1331: if (PersonDO.cache.getLevelOfCaching() == CacheConstants.QUERY_CACHING) {
1332: queryItem = ((QueryCache) PersonDO.cache)
1333: .newQueryCacheItemInstance(logicalDatabase);
1334: }
1335: }
1336:
1337: /**
1338: * Return the appropriate QueryBuilder flag for selecting
1339: * exact matches (SQL '=') or inexact matches (SQL 'matches').
1340: *
1341: * @return boolean True if it is exact match, otherwise false.
1342: *
1343: */
1344: private boolean exactFlag(boolean exact) {
1345: return exact ? QueryBuilder.EXACT_MATCH
1346: : QueryBuilder.NOT_EXACT;
1347: }
1348:
1349: //
1350: // Implementation of Query interface
1351: //
1352:
1353: /**
1354: * Method to query objects from the database.
1355: * The following call in runQuery()
1356: * dbQuery.query( this );
1357: * causes the dbQuery object to invoke
1358: * executeQuery()
1359: *
1360: * @param conn Handle to database connection.
1361: *
1362: * @return ResultSet with the results of the query.
1363: *
1364: * @exception java.sql.SQLException If a database access error occurs.
1365: */
1366: public ResultSet executeQuery(DBConnection conn)
1367: throws SQLException {
1368: builder.setCurrentFetchSize(iCurrentFetchSize);
1369: builder.setCurrentQueryTimeout(iCurrentQueryTimeout);
1370: resultSet = builder.executeQuery(conn);
1371: return resultSet;
1372: }
1373:
1374: /**
1375: * WARNING! This method is disabled.
1376: * It's implementation is forced by the Query interface.
1377: * This method is disabled for 2 reasons:
1378: * 1) the getDOArray() and getNextDO() methods are better
1379: * because they return DOs instead of JDBC objects.
1380: * 2) the createExisting() method throws an exception
1381: * that we cannot reasonably handle here,
1382: * and that we cannot throw from here.
1383: *
1384: * @param rs JDBC result set from which the next object
1385: * will be instantiated.
1386: *
1387: * @exception java.sql.SQLException
1388: * If a database access error occurs.
1389: * @exception com.lutris.appserver.server.sql.ObjectIdException
1390: * If an invalid object id was queried from the database.
1391: */
1392: public Object next(ResultSet rs) throws SQLException,
1393: ObjectIdException {
1394: // TODO: It would be nice to throw an unchecked exception here
1395: // (an exception that extends RuntimeException)
1396: // that would be guaranteed to appear during application testing.
1397: throw new ObjectIdException(
1398: "next() should not be used. Use getNextDO() instead.");
1399: //return null;
1400: }
1401:
1402: // WebDocWf extension for extended wildcard support
1403: // The following lines have been added:
1404: /**
1405: * Convert a String with user wildcards into a string with DB wildcards
1406: *
1407: * @param userSearchValue The string with user wildcards
1408: *
1409: * @return The string with DB wildcards
1410: *
1411: * WebDocWf extension
1412: *
1413: */
1414: public String convertUserSearchValue(String userSearchValue) {
1415: return builder.convertUserSearchValue(userSearchValue);
1416: }
1417:
1418: /**
1419: * Check whether a string contains DB wildcards
1420: *
1421: * @param dbSearchValue The string with possible DB wildcards
1422: *
1423: * @return Whether a string contains DB wildcards
1424: *
1425: * WebDocWf extension
1426: *
1427: */
1428: public boolean containsWildcards(String dbSearchValue) {
1429: return builder.containsWildcards(dbSearchValue);
1430: }
1431:
1432: // end of WebDocWf extension for extended wildcard support
1433:
1434: // WebDocWf extension for query row counter
1435: // The following lines have been added:
1436: /**
1437: * Get the rowcount of the query
1438: * If possible, do it without reading all rows
1439: *
1440: * @return The row count
1441: *
1442: * WebDocWf extension
1443: *
1444: */
1445: public int getCount() throws NonUniqueQueryException,
1446: DataObjectException, SQLException, DatabaseManagerException {
1447: int rowCount = 0;
1448: if (needToRun && databaseLimit == 0) {
1449: rowCount = selectCount();
1450: } else {
1451: if (needToRun)
1452: runQuery();
1453: rowCount = DOs.length;
1454: }
1455: return rowCount;
1456: }
1457:
1458: /**
1459: * Set reference objects
1460: *
1461: */
1462: protected void setRefs(HashMap queryRefs) {
1463: refs = queryRefs;
1464: }
1465:
1466: /**
1467: * Set fetch size for this query
1468: *
1469: */
1470: public void set_FetchSize(int iCurrentFetchSizeIn) {
1471: iCurrentFetchSize = iCurrentFetchSizeIn;
1472: }
1473:
1474: /**
1475: * reads the current fetchsize for this query
1476: * @return the current fetchsize; if -1 the no fetchsize is defined, defaultFetchSize will be use if defined
1477: */
1478: public int get_FetchSize() {
1479: return (iCurrentFetchSize < 0) ? builder.getDefaultFetchSize()
1480: : iCurrentFetchSize;
1481: }
1482:
1483: /**
1484: * reads the current queryTimeout for this query
1485: * @return the current queryTimeout;
1486: */
1487: public int get_QueryTimeout() {
1488: return iCurrentQueryTimeout;
1489: }
1490:
1491: /**
1492: * set the current queryTimeout for this query
1493: * @return the current queryTimeout;
1494: */
1495: public void set_QueryTimeout(int iQueryTimeoutIn) {
1496: iCurrentQueryTimeout = (iCurrentQueryTimeout < 0) ? builder
1497: .getDefaultQueryTimeout() : iCurrentQueryTimeout;
1498: }
1499:
1500: /**
1501: * Get the rowcount of the query by using count(*) in the DB
1502: *
1503: * @return The row count
1504: *
1505: * WebDocWf extension
1506: *
1507: */
1508: public int selectCount() throws SQLException,
1509: DatabaseManagerException {
1510: int rowCount = 0;
1511: String tempClause = builder.getSelectClause();
1512: builder.setSelectClause(" count(*) as \"counter\" ");
1513: DBQuery dbQuery;
1514:
1515: dbQuery = PersonDO.createQuery(transaction);
1516: dbQuery.query(this );
1517: resultSet.next();
1518: rowCount = resultSet.getInt("counter");
1519: resultSet.close();
1520: if (transaction == null)
1521: dbQuery.release();
1522: builder.close();
1523: resultSet = null;
1524: builder.setSelectClause(tempClause);
1525: return rowCount;
1526: }
1527:
1528: // end of WebDocWf extension for query row counter
1529:
1530: /**
1531: * Return true if some caching for this table is enabled.
1532: * @return (true/false)
1533: */
1534:
1535: private boolean isCaching() {
1536: double cachePercentage = PersonDO.cache.getCachePercentage();
1537: double usedPercentage = 0;
1538: if (cachePercentage == -1)
1539: return false;
1540: else if (cachePercentage == 0)
1541: return true;
1542: else {
1543: try {
1544: usedPercentage = PersonDO
1545: .getConfigurationAdministration()
1546: .getStatistics().getCacheStatistics(
1547: CacheConstants.DATA_CACHE)
1548: .getUsedPercents();
1549: } catch (Exception ex) {
1550: return false;
1551: }
1552: if (usedPercentage > PersonDO.cache.getCachePercentage() * 100)
1553: return true;
1554: else
1555: return false;
1556: }
1557: }
1558:
1559: private static StandardDBTransaction _tr_(DBTransaction dbt) {
1560: return (StandardDBTransaction) dbt;
1561: }
1562:
1563: /**
1564: * Set the firstName to query, with a QueryBuilder comparison operator.
1565: *
1566: * @param x The firstName of the person to query.
1567: * @param cmp_op QueryBuilder comparison operator to use.
1568: *
1569: * @exception DataObjectException If a database access error occurs.
1570: * @exception QueryException If comparison operator is inappropriate
1571: * (e.g. CASE_SENSITIVE_CONTAINS on an integer field).
1572: */
1573:
1574: public void setQueryFirstName(String x, String cmp_op)
1575: throws DataObjectException, QueryException {
1576:
1577: String cachePrefix = getLogicalDatabase() + ".";
1578:
1579: hasNonOidCond = true;
1580: Condition cond = new Condition(
1581: PersonDataStruct.COLUMN_FIRSTNAME, x, cmp_op);
1582: queryItem.addCond(cond);
1583: // WebDocWf extension for extended wildcard support
1584: // The following lines have been added:
1585: if (cmp_op.equals(QueryBuilder.CASE_INSENSITIVE_MATCH)
1586: || cmp_op.equals(QueryBuilder.CASE_SENSITIVE_MATCH)
1587: || cmp_op
1588: .equals(QueryBuilder.USER_CASE_SENSITIVE_MATCH)
1589: || cmp_op
1590: .equals(QueryBuilder.USER_CASE_INSENSITIVE_MATCH)) {
1591: hitDb = true;
1592: } else {
1593: // end of WebDocWf extension for extended wildcard support
1594:
1595: if (PersonDO.cache.isFull()) {
1596: // Remove from cacheHits any DOs that do not meet this
1597: // setQuery requirement.
1598: PersonDO DO = null;
1599: PersonDataStruct DS = null;
1600: for (Iterator iter = (new HashSet(cacheHits.values()))
1601: .iterator(); iter.hasNext();) {
1602: try {
1603: boolean findInTransactionCache = false;
1604: DS = (PersonDataStruct) iter.next();
1605: if (transaction != null
1606: && _tr_(transaction)
1607: .getTransactionCache() != null) {
1608: DO = (PersonDO) _tr_(transaction)
1609: .getTransactionCache()
1610: .getDOByHandle(
1611: cachePrefix
1612: + DS.get_OId()
1613: .toString());
1614: if (DO != null)
1615: findInTransactionCache = true;
1616: }
1617: if (!findInTransactionCache) {
1618: DO = (PersonDO) PersonDO.createExisting(DS
1619: .get_OId(), transaction);
1620: }
1621: } catch (Exception ex) {
1622: System.out
1623: .println("Error in query member stuff");
1624: }
1625:
1626: String m = DO.getFirstName();
1627: if (!QueryBuilder.compare(m, x, cmp_op)) {
1628: try {
1629: String cacheHandle = DO.get_CacheHandle();
1630: cacheHits.remove(cacheHandle);
1631: } catch (DatabaseManagerException e) {
1632: throw new DataObjectException(
1633: "Error in loading data object's handle.");
1634: }
1635: }
1636: }
1637: }
1638: }
1639: // Also prepares the SQL needed to query the database
1640: // in case there is no cache, or the query involves other tables.
1641: // WebDocWf patch for correct queries in fully cached objects
1642: // The following line has been put under comments:
1643: // if ( partOrLru || hitDb )
1644: // end of WebDocWf patch for correct queries in fully cached objects
1645: builder.addWhere(PersonDO.FirstName, x, cmp_op);
1646: }
1647:
1648: /**
1649: * Set the firstName to query, with a QueryBuilder comparison operator.
1650: *
1651: * @param x The firstName of the person to query.
1652: *
1653: * @exception DataObjectException If a database access error occurs.
1654: * @exception QueryException If comparison operator is inappropriate
1655: * (e.g. CASE_SENSITIVE_CONTAINS on an integer field).
1656: */
1657: public void setQueryFirstName(String x) throws DataObjectException,
1658: QueryException {
1659: setQueryFirstName(x, QueryBuilder.EQUAL);
1660: }
1661:
1662: /**
1663: * Add firstName to the ORDER BY clause.
1664: * NOTE: The DO cache does not yet support the Order By operation.
1665: * Using the addOrderBy method forces the query to hit the database.
1666: *
1667: * @param direction_flag True for ascending order, false for descending
1668: */
1669: public void addOrderByFirstName(boolean direction_flag) {
1670: hitDb = true;
1671: builder.addOrderByColumn("firstName", (direction_flag) ? "ASC"
1672: : "DESC");
1673: }
1674:
1675: /**
1676: * Add firstName to the ORDER BY clause. This convenience
1677: * method assumes ascending order.
1678: * NOTE: The DO cache does not yet support the Order By operation.
1679: * Using the addOrderBy method forces the query to hit the database.
1680: */
1681: public void addOrderByFirstName() {
1682: hitDb = true;
1683: builder.addOrderByColumn("firstName", "ASC");
1684: }
1685:
1686: // WebDocWf extension for extended wildcard support
1687: // The following lines have been added:
1688:
1689: /**
1690: * Set the firstName to query with a user wildcard string
1691: *
1692: * @param x The firstName of the person to query with user wildcards
1693: *
1694: * @exception DataObjectException If a database access error occurs.
1695: *
1696: * @deprecated Use comparison operators instead
1697: *
1698: * WebDocWf extension
1699: *
1700: */
1701: public void setUserMatchFirstName(String x)
1702: throws DataObjectException, QueryException {
1703: String y = convertUserSearchValue(x);
1704: setDBMatchFirstName(y);
1705: }
1706:
1707: /**
1708: * Set the firstName to query with a DB wildcard string
1709: *
1710: * @param x The firstName of the person to query with DB wildcards
1711: *
1712: * @exception DataObjectException If a database access error occurs.
1713: *
1714: * @deprecated Use comparison operators instead
1715: *
1716: * WebDocWf extension
1717: *
1718: */
1719: public void setDBMatchFirstName(String x)
1720: throws DataObjectException, QueryException {
1721: if (containsWildcards(x)
1722: || builder.getUserStringAppendWildcard()) {
1723: builder.addMatchClause(PersonDO.FirstName, x);
1724: hitDb = true;
1725: } else
1726: setQueryFirstName(x, QueryBuilder.EQUAL);
1727: }
1728:
1729: // end of WebDocWf extension for extended wildcard support
1730:
1731: /**
1732: * Set the lastName to query, with a QueryBuilder comparison operator.
1733: *
1734: * @param x The lastName of the person to query.
1735: * @param cmp_op QueryBuilder comparison operator to use.
1736: *
1737: * @exception DataObjectException If a database access error occurs.
1738: * @exception QueryException If comparison operator is inappropriate
1739: * (e.g. CASE_SENSITIVE_CONTAINS on an integer field).
1740: */
1741:
1742: public void setQueryLastName(String x, String cmp_op)
1743: throws DataObjectException, QueryException {
1744:
1745: String cachePrefix = getLogicalDatabase() + ".";
1746:
1747: hasNonOidCond = true;
1748: Condition cond = new Condition(
1749: PersonDataStruct.COLUMN_LASTNAME, x, cmp_op);
1750: queryItem.addCond(cond);
1751: // WebDocWf extension for extended wildcard support
1752: // The following lines have been added:
1753: if (cmp_op.equals(QueryBuilder.CASE_INSENSITIVE_MATCH)
1754: || cmp_op.equals(QueryBuilder.CASE_SENSITIVE_MATCH)
1755: || cmp_op
1756: .equals(QueryBuilder.USER_CASE_SENSITIVE_MATCH)
1757: || cmp_op
1758: .equals(QueryBuilder.USER_CASE_INSENSITIVE_MATCH)) {
1759: hitDb = true;
1760: } else {
1761: // end of WebDocWf extension for extended wildcard support
1762:
1763: if (PersonDO.cache.isFull()) {
1764: // Remove from cacheHits any DOs that do not meet this
1765: // setQuery requirement.
1766: PersonDO DO = null;
1767: PersonDataStruct DS = null;
1768: for (Iterator iter = (new HashSet(cacheHits.values()))
1769: .iterator(); iter.hasNext();) {
1770: try {
1771: boolean findInTransactionCache = false;
1772: DS = (PersonDataStruct) iter.next();
1773: if (transaction != null
1774: && _tr_(transaction)
1775: .getTransactionCache() != null) {
1776: DO = (PersonDO) _tr_(transaction)
1777: .getTransactionCache()
1778: .getDOByHandle(
1779: cachePrefix
1780: + DS.get_OId()
1781: .toString());
1782: if (DO != null)
1783: findInTransactionCache = true;
1784: }
1785: if (!findInTransactionCache) {
1786: DO = (PersonDO) PersonDO.createExisting(DS
1787: .get_OId(), transaction);
1788: }
1789: } catch (Exception ex) {
1790: System.out
1791: .println("Error in query member stuff");
1792: }
1793:
1794: String m = DO.getLastName();
1795: if (!QueryBuilder.compare(m, x, cmp_op)) {
1796: try {
1797: String cacheHandle = DO.get_CacheHandle();
1798: cacheHits.remove(cacheHandle);
1799: } catch (DatabaseManagerException e) {
1800: throw new DataObjectException(
1801: "Error in loading data object's handle.");
1802: }
1803: }
1804: }
1805: }
1806: }
1807: // Also prepares the SQL needed to query the database
1808: // in case there is no cache, or the query involves other tables.
1809: // WebDocWf patch for correct queries in fully cached objects
1810: // The following line has been put under comments:
1811: // if ( partOrLru || hitDb )
1812: // end of WebDocWf patch for correct queries in fully cached objects
1813: builder.addWhere(PersonDO.LastName, x, cmp_op);
1814: }
1815:
1816: /**
1817: * Set the lastName to query, with a QueryBuilder comparison operator.
1818: *
1819: * @param x The lastName of the person to query.
1820: *
1821: * @exception DataObjectException If a database access error occurs.
1822: * @exception QueryException If comparison operator is inappropriate
1823: * (e.g. CASE_SENSITIVE_CONTAINS on an integer field).
1824: */
1825: public void setQueryLastName(String x) throws DataObjectException,
1826: QueryException {
1827: setQueryLastName(x, QueryBuilder.EQUAL);
1828: }
1829:
1830: /**
1831: * Add lastName to the ORDER BY clause.
1832: * NOTE: The DO cache does not yet support the Order By operation.
1833: * Using the addOrderBy method forces the query to hit the database.
1834: *
1835: * @param direction_flag True for ascending order, false for descending
1836: */
1837: public void addOrderByLastName(boolean direction_flag) {
1838: hitDb = true;
1839: builder.addOrderByColumn("lastName", (direction_flag) ? "ASC"
1840: : "DESC");
1841: }
1842:
1843: /**
1844: * Add lastName to the ORDER BY clause. This convenience
1845: * method assumes ascending order.
1846: * NOTE: The DO cache does not yet support the Order By operation.
1847: * Using the addOrderBy method forces the query to hit the database.
1848: */
1849: public void addOrderByLastName() {
1850: hitDb = true;
1851: builder.addOrderByColumn("lastName", "ASC");
1852: }
1853:
1854: // WebDocWf extension for extended wildcard support
1855: // The following lines have been added:
1856:
1857: /**
1858: * Set the lastName to query with a user wildcard string
1859: *
1860: * @param x The lastName of the person to query with user wildcards
1861: *
1862: * @exception DataObjectException If a database access error occurs.
1863: *
1864: * @deprecated Use comparison operators instead
1865: *
1866: * WebDocWf extension
1867: *
1868: */
1869: public void setUserMatchLastName(String x)
1870: throws DataObjectException, QueryException {
1871: String y = convertUserSearchValue(x);
1872: setDBMatchLastName(y);
1873: }
1874:
1875: /**
1876: * Set the lastName to query with a DB wildcard string
1877: *
1878: * @param x The lastName of the person to query with DB wildcards
1879: *
1880: * @exception DataObjectException If a database access error occurs.
1881: *
1882: * @deprecated Use comparison operators instead
1883: *
1884: * WebDocWf extension
1885: *
1886: */
1887: public void setDBMatchLastName(String x)
1888: throws DataObjectException, QueryException {
1889: if (containsWildcards(x)
1890: || builder.getUserStringAppendWildcard()) {
1891: builder.addMatchClause(PersonDO.LastName, x);
1892: hitDb = true;
1893: } else
1894: setQueryLastName(x, QueryBuilder.EQUAL);
1895: }
1896:
1897: // end of WebDocWf extension for extended wildcard support
1898:
1899: /**
1900: * Set the phoneNumber to query, with a QueryBuilder comparison operator.
1901: *
1902: * @param x The phoneNumber of the person to query.
1903: * @param cmp_op QueryBuilder comparison operator to use.
1904: *
1905: * @exception DataObjectException If a database access error occurs.
1906: * @exception QueryException If comparison operator is inappropriate
1907: * (e.g. CASE_SENSITIVE_CONTAINS on an integer field).
1908: */
1909:
1910: public void setQueryPhoneNumber(String x, String cmp_op)
1911: throws DataObjectException, QueryException {
1912:
1913: String cachePrefix = getLogicalDatabase() + ".";
1914:
1915: hasNonOidCond = true;
1916: Condition cond = new Condition(
1917: PersonDataStruct.COLUMN_PHONENUMBER, x, cmp_op);
1918: queryItem.addCond(cond);
1919: // WebDocWf extension for extended wildcard support
1920: // The following lines have been added:
1921: if (cmp_op.equals(QueryBuilder.CASE_INSENSITIVE_MATCH)
1922: || cmp_op.equals(QueryBuilder.CASE_SENSITIVE_MATCH)
1923: || cmp_op
1924: .equals(QueryBuilder.USER_CASE_SENSITIVE_MATCH)
1925: || cmp_op
1926: .equals(QueryBuilder.USER_CASE_INSENSITIVE_MATCH)) {
1927: hitDb = true;
1928: } else {
1929: // end of WebDocWf extension for extended wildcard support
1930:
1931: if (PersonDO.cache.isFull()) {
1932: // Remove from cacheHits any DOs that do not meet this
1933: // setQuery requirement.
1934: PersonDO DO = null;
1935: PersonDataStruct DS = null;
1936: for (Iterator iter = (new HashSet(cacheHits.values()))
1937: .iterator(); iter.hasNext();) {
1938: try {
1939: boolean findInTransactionCache = false;
1940: DS = (PersonDataStruct) iter.next();
1941: if (transaction != null
1942: && _tr_(transaction)
1943: .getTransactionCache() != null) {
1944: DO = (PersonDO) _tr_(transaction)
1945: .getTransactionCache()
1946: .getDOByHandle(
1947: cachePrefix
1948: + DS.get_OId()
1949: .toString());
1950: if (DO != null)
1951: findInTransactionCache = true;
1952: }
1953: if (!findInTransactionCache) {
1954: DO = (PersonDO) PersonDO.createExisting(DS
1955: .get_OId(), transaction);
1956: }
1957: } catch (Exception ex) {
1958: System.out
1959: .println("Error in query member stuff");
1960: }
1961:
1962: String m = DO.getPhoneNumber();
1963: if (!QueryBuilder.compare(m, x, cmp_op)) {
1964: try {
1965: String cacheHandle = DO.get_CacheHandle();
1966: cacheHits.remove(cacheHandle);
1967: } catch (DatabaseManagerException e) {
1968: throw new DataObjectException(
1969: "Error in loading data object's handle.");
1970: }
1971: }
1972: }
1973: }
1974: }
1975: // Also prepares the SQL needed to query the database
1976: // in case there is no cache, or the query involves other tables.
1977: // WebDocWf patch for correct queries in fully cached objects
1978: // The following line has been put under comments:
1979: // if ( partOrLru || hitDb )
1980: // end of WebDocWf patch for correct queries in fully cached objects
1981: builder.addWhere(PersonDO.PhoneNumber, x, cmp_op);
1982: }
1983:
1984: /**
1985: * Set the phoneNumber to query, with a QueryBuilder comparison operator.
1986: *
1987: * @param x The phoneNumber of the person to query.
1988: *
1989: * @exception DataObjectException If a database access error occurs.
1990: * @exception QueryException If comparison operator is inappropriate
1991: * (e.g. CASE_SENSITIVE_CONTAINS on an integer field).
1992: */
1993: public void setQueryPhoneNumber(String x)
1994: throws DataObjectException, QueryException {
1995: setQueryPhoneNumber(x, QueryBuilder.EQUAL);
1996: }
1997:
1998: /**
1999: * Add phoneNumber to the ORDER BY clause.
2000: * NOTE: The DO cache does not yet support the Order By operation.
2001: * Using the addOrderBy method forces the query to hit the database.
2002: *
2003: * @param direction_flag True for ascending order, false for descending
2004: */
2005: public void addOrderByPhoneNumber(boolean direction_flag) {
2006: hitDb = true;
2007: builder.addOrderByColumn("phoneNumber",
2008: (direction_flag) ? "ASC" : "DESC");
2009: }
2010:
2011: /**
2012: * Add phoneNumber to the ORDER BY clause. This convenience
2013: * method assumes ascending order.
2014: * NOTE: The DO cache does not yet support the Order By operation.
2015: * Using the addOrderBy method forces the query to hit the database.
2016: */
2017: public void addOrderByPhoneNumber() {
2018: hitDb = true;
2019: builder.addOrderByColumn("phoneNumber", "ASC");
2020: }
2021:
2022: // WebDocWf extension for extended wildcard support
2023: // The following lines have been added:
2024:
2025: /**
2026: * Set the phoneNumber to query with a user wildcard string
2027: *
2028: * @param x The phoneNumber of the person to query with user wildcards
2029: *
2030: * @exception DataObjectException If a database access error occurs.
2031: *
2032: * @deprecated Use comparison operators instead
2033: *
2034: * WebDocWf extension
2035: *
2036: */
2037: public void setUserMatchPhoneNumber(String x)
2038: throws DataObjectException, QueryException {
2039: String y = convertUserSearchValue(x);
2040: setDBMatchPhoneNumber(y);
2041: }
2042:
2043: /**
2044: * Set the phoneNumber to query with a DB wildcard string
2045: *
2046: * @param x The phoneNumber of the person to query with DB wildcards
2047: *
2048: * @exception DataObjectException If a database access error occurs.
2049: *
2050: * @deprecated Use comparison operators instead
2051: *
2052: * WebDocWf extension
2053: *
2054: */
2055: public void setDBMatchPhoneNumber(String x)
2056: throws DataObjectException, QueryException {
2057: if (containsWildcards(x)
2058: || builder.getUserStringAppendWildcard()) {
2059: builder.addMatchClause(PersonDO.PhoneNumber, x);
2060: hitDb = true;
2061: } else
2062: setQueryPhoneNumber(x, QueryBuilder.EQUAL);
2063: }
2064:
2065: // end of WebDocWf extension for extended wildcard support
2066:
2067: /**
2068: * Returns the <code>QueryBuilder</code> that this <code>PersonQuery</code>
2069: * uses to construct and execute database queries.
2070: * <code>PersonQuery.setQueryXXX</code> methods use
2071: * the <code>QueryBuilder</code> to
2072: * append SQL expressions to the <code>"WHERE"</code> clause to be executed.
2073: * The <code>QueryBuilder.addEndClause method.</code> can be used to
2074: * append freeform SQL expressions to the <code>WHERE</code> clause,
2075: * e.g. "ORDER BY name".
2076: *
2077: * <b>Notes regarding cache-enabled DO classes:</b>
2078: * DO classes can be cache-enabled.
2079: * If when using a <code>PersonQuery</code>, the application developer
2080: * <b>does not call</b> <code>getQueryBuilder</code>,
2081: * then <code>PersonQuery.setQueryXXX</code> methods
2082: * simply prune the DO cache and return the remaining results.
2083: * However, a <code>QueryBuilder</code> builds
2084: * <CODE>SELECT</CODE> statements for execution by the actual database,
2085: * and never searches the built-in cache for the DO.
2086: * So, if the DO class is cache-enabled, and <code>getQueryBuilder</code>
2087: * is called, this <CODE>PersonQuery</CODE> object ignores the cache
2088: * and hits the actual database.
2089: *
2090: * @return QueryBuilder that is used to construct and execute database queries.
2091: */
2092: public QueryBuilder getQueryBuilder() {
2093: hitDb = true;
2094: return builder;
2095: }
2096:
2097: /**
2098: * Insert an <CODE>OR</CODE> between <CODE>WHERE</CODE> clauses.
2099: * Example: find all the persons named Bob or Robert:
2100: * <CODE>
2101: * PersonQuery pq = new PersonQuery();
2102: * pq.setQueryFirstName( "Bob" );
2103: * pq.or();
2104: * pq.setQueryFirstName( "Robert" );
2105: * </CODE>
2106: *
2107: * Note: Calls to <CODE>setQueryXxx</CODE> methods
2108: * are implicitly <CODE>AND</CODE>ed together,
2109: * so the following example will always return nothing:
2110: * <CODE>
2111: * PersonQuery pq = new PersonQuery();
2112: * pq.setQueryFirstName( "Bob" );
2113: * // AND automatically inserted here.
2114: * pq.setQueryFirstName( "Robert" );
2115: * </CODE>
2116:
2117: *
2118: * NOTE: The DO cache does not yet support the OR operator.
2119: * Using the or() method forces the query to hit the database.
2120:
2121: *
2122: * @see QueryBuilder to construct more elaborate queries.
2123: * @author Jay Gunter
2124: */
2125: public void or() {
2126: hitDb = true;
2127: builder.addWhereOr();
2128: }
2129:
2130: /**
2131: * Place an open parenthesis in the <CODE>WHERE</CODE> clause.
2132: * Example usage: find all the Bobs and Roberts who are 5 or 50 years old:
2133: * <CODE>
2134: * PersonQuery pq = new PersonQuery();
2135: * pq.openParen();
2136: * pq.setQueryFirstName( "Bob" );
2137: * pq.or();
2138: * pq.setQueryFirstName( "Robert" );
2139: * pq.closeParen();
2140: * // AND automatically inserted here.
2141: * pq.openParen();
2142: * pq.setQueryAge( 5 );
2143: * pq.or();
2144: * pq.setQueryAge( 50 );
2145: * pq.closeParen();
2146: * </CODE>
2147:
2148: *
2149: * NOTE: The DO cache does not yet support the Open Paren operator.
2150: * Using the openParen() method forces the query to hit the database.
2151:
2152: *
2153: * @see QueryBuilder to construct more elaborate queries.
2154: * @author Jay Gunter
2155: */
2156: public void openParen() {
2157: hitDb = true;
2158: builder.addWhereOpenParen();
2159: }
2160:
2161: /**
2162: * Place a closing parenthesis in the <CODE>WHERE</CODE> clause.
2163:
2164: *
2165: * NOTE: The DO cache does not yet support the Close Paren operator.
2166: * Using the closeParen() method forces the query to hit the database.
2167:
2168: *
2169: * @see openParen
2170: * @author Jay Gunter
2171: */
2172: public void closeParen() {
2173: hitDb = true;
2174: builder.addWhereCloseParen();
2175: }
2176: }
|