0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * // Copyright (c) 1998, 2007, Oracle. All rights reserved.
0005: *
0006: *
0007: * The contents of this file are subject to the terms of either the GNU
0008: * General Public License Version 2 only ("GPL") or the Common Development
0009: * and Distribution License("CDDL") (collectively, the "License"). You
0010: * may not use this file except in compliance with the License. You can obtain
0011: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
0012: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
0013: * language governing permissions and limitations under the License.
0014: *
0015: * When distributing the software, include this License Header Notice in each
0016: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
0017: * Sun designates this particular file as subject to the "Classpath" exception
0018: * as provided by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the License
0020: * Header, with the fields enclosed by brackets [] replaced by your own
0021: * identifying information: "Portions Copyrighted [year]
0022: * [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * If you wish your version of this file to be governed by only the CDDL or
0027: * only the GPL Version 2, indicate your decision by adding "[Contributor]
0028: * elects to include this software in this distribution under the [CDDL or GPL
0029: * Version 2] license." If you don't indicate a single choice of license, a
0030: * recipient has the option to distribute your version of this file under
0031: * either the CDDL, the GPL Version 2 or to extend the choice of license to
0032: * its licensees as provided above. However, if you add GPL Version 2 code
0033: * and therefore, elected the GPL Version 2 license, then the option applies
0034: * only if the new code is made subject to such option by the copyright
0035: * holder.
0036: */
0037: package oracle.toplink.essentials.queryframework;
0038:
0039: import java.util.*;
0040: import java.io.*;
0041: import oracle.toplink.essentials.internal.helper.*;
0042: import oracle.toplink.essentials.expressions.*;
0043: import oracle.toplink.essentials.internal.expressions.*;
0044: import oracle.toplink.essentials.internal.databaseaccess.*;
0045: import oracle.toplink.essentials.internal.queryframework.*;
0046: import oracle.toplink.essentials.exceptions.*;
0047: import oracle.toplink.essentials.sessions.Record;
0048: import oracle.toplink.essentials.sessions.DatabaseRecord;
0049: import oracle.toplink.essentials.internal.parsing.ejbql.EJBQLCallQueryMechanism;
0050: import oracle.toplink.essentials.sessions.SessionProfiler;
0051: import oracle.toplink.essentials.internal.sessions.AbstractRecord;
0052: import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
0053: import oracle.toplink.essentials.internal.sessions.AbstractSession;
0054: import oracle.toplink.essentials.descriptors.ClassDescriptor;
0055:
0056: /**
0057: * <p><b>Purpose</b>:
0058: * Abstract class for all database query objects.
0059: * DatabaseQuery is a visible class to the TopLink user. Users create an appropriate
0060: * query by creating an instance of a concrete subclasses of DatabaseQuery.
0061: *
0062: * <p><b>Responsibilities</b>:
0063: * <ul>
0064: * <li> Provide a common protocol for query objects.
0065: * <li> Defines a generic execution interface.
0066: * <li> Provides query property values
0067: * <li> Holds arguments to the query
0068: * </ul>
0069: *
0070: * @author Yvon Lavoie
0071: * @since TOPLink/Java 1.0
0072: */
0073: public abstract class DatabaseQuery implements Cloneable, Serializable,
0074: FalseUndefinedTrue {
0075:
0076: /** Queries can be given a name and registered with a descriptor to allow common queries to be reused. */
0077: protected String name;
0078:
0079: /** Arguments can be given and specified to predefined queries to allow reuse. */
0080: protected Vector arguments;
0081:
0082: /** Arguments values can be given and specified to predefined queries to allow reuse. */
0083: protected Vector argumentValues;
0084:
0085: /** Needed to differentiate queries with the same name. */
0086: protected Vector argumentTypes;
0087:
0088: /** Used to build a list of argumentTypes by name pre-initialization */
0089: protected Vector argumentTypeNames;
0090:
0091: /** The descriptor cached on the prepare for object level queries. */
0092: protected transient ClassDescriptor descriptor;
0093:
0094: /** The query mechanism determines the mechanism on how the database will be accessed. */
0095: protected DatabaseQueryMechanism queryMechanism;
0096:
0097: /** Flag used for a query to bypass the identitymap and unit of work. */
0098: // Bug#3476483 - Restore shouldMaintainCache to previous state after reverse of bug fix 3240668
0099: protected boolean shouldMaintainCache;
0100:
0101: /** Internallay used by the mappings as a temporary store. */
0102: protected Hashtable properties;
0103:
0104: /** Only used after the query is prepared to store the session under which the query was executed. */
0105: protected transient AbstractSession session;
0106:
0107: /** Connection to use for database access, required for server session connection pooling. */
0108: protected transient Accessor accessor;
0109:
0110: /** Mappings and the descriptor use parameterized mechanisms that will be translated with the data from the row. */
0111: protected AbstractRecord translationRow;
0112:
0113: /** Internal flag used to bypass user define queries when executing one for custom sql/query support. */
0114: protected boolean isUserDefined;
0115:
0116: /** Policy that determines how the query will cascade to its object's parts. */
0117: protected int cascadePolicy;
0118:
0119: /** Used to override the default session in the session broker. */
0120: protected String sessionName;
0121:
0122: /** Queries prepare common stated in themselves. */
0123: protected boolean isPrepared;
0124:
0125: /** Used to indicate whether or not the call needs to be cloned. */
0126: protected boolean shouldCloneCall;
0127:
0128: /** Allow for the prepare of queries to be turned off, this allow for dynamic non-pre SQL generated queries. */
0129: protected boolean shouldPrepare;
0130:
0131: /** Bind all arguments to the SQL statement. */
0132:
0133: // Has False, Underfined or True value. In case of Undefined -
0134: // Session's shouldBindAllParameters() defines whether to bind or not.
0135: protected int shouldBindAllParameters;
0136:
0137: /** Cache the prepared statement, this requires full parameter binding as well. */
0138:
0139: // Has False, Underfined or True value. In case of Undefined -
0140: // Session's shouldCacheAllStatements() defines whether to cache or not.
0141: protected int shouldCacheStatement;
0142:
0143: /** Use the WrapperPolicy for the objects returned by the query */
0144: protected boolean shouldUseWrapperPolicy;
0145:
0146: /* Used as default for read, means shallow write for modify. */
0147: public static final int NoCascading = 1;
0148:
0149: /* Used as default for write, used for refreshing to refresh the whole object. */
0150: public static final int CascadePrivateParts = 2;
0151:
0152: /* Currently not supported, used for deep write/refreshes/reads in the future. */
0153: public static final int CascadeAllParts = 3;
0154:
0155: /* Used by the unit of work. */
0156: public static final int CascadeDependentParts = 4;
0157:
0158: /* Used by aggregate Collections: As aggregates delete at update time, cascaded deletes
0159: * must know to stop when entering postDelete for a particular mapping. Only used by the
0160: * aggregate collection when update is occuring in a UnitOfWork
0161: * CR 2811
0162: */
0163: public static final int CascadeAggregateDelete = 5;
0164:
0165: /*
0166: * Used when refreshing should check the mappings to determin if a particular
0167: * mapping should be cascaded.
0168: */
0169: public static final int CascadeByMapping = 6;
0170:
0171: /*
0172: * Stores the FlushMode of this Query. This is only applicable when executed
0173: * in a flushable UnitOfWork and will be ignored otherwise.
0174: */
0175: protected Boolean flushOnExecute;
0176:
0177: /**
0178: * PUBLIC:
0179: * Initialize the state of the query
0180: */
0181: public DatabaseQuery() {
0182: this .shouldMaintainCache = true;
0183: // bug 3524620: lazy-init query mechanism
0184: //this.queryMechanism = new ExpressionQueryMechanism(this);
0185: this .isUserDefined = false;
0186: this .cascadePolicy = NoCascading;
0187: this .isPrepared = false;
0188: this .shouldUseWrapperPolicy = true;
0189: this .shouldPrepare = true;
0190: this .shouldBindAllParameters = Undefined;
0191: this .shouldCacheStatement = Undefined;
0192: this .shouldCloneCall = false;
0193: }
0194:
0195: /**
0196: * PUBLIC:
0197: * Add the argument named argumentName.
0198: * This will cause the translation of references of argumentName in the receiver's expression,
0199: * with the value of the argument as supplied to the query in order from executeQuery()
0200: */
0201: public void addArgument(String argumentName) {
0202: // CR#3545 - Changed the default argument type to make argument types work more consistently
0203: // with the SDK
0204: addArgument(argumentName, java.lang.Object.class);
0205: }
0206:
0207: /**
0208: * PUBLIC:
0209: * Add the argument named argumentName and its class type.
0210: * This will cause the translation of references of argumentName in the receiver's expression,
0211: * with the value of the argument as supplied to the query in order from executeQuery().
0212: * Specifying the class type is important if identically named queries are used but with
0213: * different argument lists.
0214: */
0215: public void addArgument(String argumentName, Class type) {
0216: getArguments().addElement(argumentName);
0217: getArgumentTypes().addElement(type);
0218: getArgumentTypeNames().addElement(type.getName());
0219: }
0220:
0221: /**
0222: * PUBLIC:
0223: * Add the argument named argumentName and its class type.
0224: * This will cause the translation of references of argumentName in the receiver's expression,
0225: * with the value of the argument as supplied to the query in order from executeQuery().
0226: * Specifying the class type is important if identically named queries are used but with
0227: * different argument lists.
0228: */
0229: public void addArgument(String argumentName, String typeAsString) {
0230: getArguments().addElement(argumentName);
0231: //bug 3197587
0232: getArgumentTypes().addElement(
0233: Helper.getObjectClass(ConversionManager
0234: .loadClass(typeAsString)));
0235: getArgumentTypeNames().addElement(typeAsString);
0236: }
0237:
0238: /**
0239: * INTERNAL:
0240: * Add an argument to the query, but do not resovle the class yet.
0241: * This is useful for building a query without putting the domain classes
0242: * on the classpath for the Mapping Workbench.
0243: */
0244: public void addArgumentByTypeName(String argumentName,
0245: String typeAsString) {
0246: getArguments().addElement(argumentName);
0247: getArgumentTypeNames().addElement(typeAsString);
0248: }
0249:
0250: /**
0251: * PUBLIC:
0252: * Add the argumentValue.
0253: * Argument values must be added in the same order the arguments are defined.
0254: */
0255: public void addArgumentValue(Object argumentValue) {
0256: getArgumentValues().addElement(argumentValue);
0257: }
0258:
0259: /**
0260: * PUBLIC:
0261: * Add the argumentValues to the query.
0262: * Argument values must be added in the same order the arguments are defined.
0263: */
0264: public void addArgumentValues(Vector theArgumentValues) {
0265: setArgumentValues(theArgumentValues);
0266: }
0267:
0268: /**
0269: * PUBLIC:
0270: * Used to define a store procedure or SQL query.
0271: * This may be used for multiple SQL executions to be mapped to a single query.
0272: * This cannot be used for cursored selects, delete alls or does exists.
0273: */
0274: public void addCall(Call call) {
0275: setQueryMechanism(call.buildQueryMechanism(this ,
0276: getQueryMechanism()));
0277: // Must un-prepare is prepare as the SQL may change.
0278: setIsPrepared(false);
0279: }
0280:
0281: /**
0282: * PUBLIC:
0283: * Used to define a statement level query.
0284: * This may be used for multiple SQL executions to be mapped to a single query.
0285: * This cannot be used for cursored selects, delete alls or does exists.
0286: */
0287: public void addStatement(SQLStatement statement) {
0288: // bug 3524620: lazy-init query mechanism
0289: if (!hasQueryMechanism()) {
0290: setQueryMechanism(new StatementQueryMechanism(this ));
0291: } else if (!getQueryMechanism().isStatementQueryMechanism()) {
0292: setQueryMechanism(new StatementQueryMechanism(this ));
0293: }
0294: ((StatementQueryMechanism) getQueryMechanism())
0295: .getSQLStatements().addElement(statement);
0296: // Must un-prepare is prepare as the SQL may change.
0297: setIsPrepared(false);
0298: }
0299:
0300: /**
0301: * PUBLIC:
0302: * Bind all arguments to any SQL statement.
0303: */
0304: public void bindAllParameters() {
0305: setShouldBindAllParameters(true);
0306: }
0307:
0308: /**
0309: * INTERNAL:
0310: * In the case of EJBQL, an expression needs to be generated. Build the required expression.
0311: */
0312: protected void buildSelectionCriteria(AbstractSession session) {
0313: this .getQueryMechanism().buildSelectionCriteria(session);
0314: }
0315:
0316: /**
0317: * PUBLIC:
0318: * Cache the prepared statements, this requires full parameter binding as well.
0319: */
0320: public void cacheStatement() {
0321: setShouldCacheStatement(true);
0322: }
0323:
0324: /**
0325: * PUBLIC:
0326: * Cascade the query and its properties on the queries object(s) and all objects related to the queries object(s).
0327: * This includes private and independent relationships, but not read-only relationships.
0328: * This will still stop on uninstantiated indirection objects except for deletion.
0329: * Great caution should be used in using the property as the query may effect a large number of objects.
0330: * This policy is used by the unit of work to ensure persistence by reachability.
0331: */
0332: public void cascadeAllParts() {
0333: setCascadePolicy(CascadeAllParts);
0334: }
0335:
0336: /**
0337: * PUBLIC:
0338: * Cascade the query and its properties on the queries object(s) and all related objects where the mapping has
0339: * been set to cascade the merge.
0340: */
0341: public void cascadeByMapping() {
0342: setCascadePolicy(CascadeByMapping);
0343: }
0344:
0345: /**
0346: * INTERNAL:
0347: * Used by unit of work, only cascades constraint dependecies.
0348: */
0349: public void cascadeOnlyDependentParts() {
0350: setCascadePolicy(CascadeDependentParts);
0351: }
0352:
0353: /**
0354: * PUBLIC:
0355: * Cascade the query and its properties on the queries object(s)
0356: * and all privately owned objects related to the queries object(s).
0357: * This is the default for write and delete queries.
0358: * This policy should normally be used for refreshing, otherwise you could refresh half of any object.
0359: */
0360: public void cascadePrivateParts() {
0361: setCascadePolicy(CascadePrivateParts);
0362: }
0363:
0364: /**
0365: * INTERNAL:
0366: * Ensure that the descriptor has been set.
0367: */
0368: public void checkDescriptor(AbstractSession session)
0369: throws QueryException {
0370: }
0371:
0372: /**
0373: * INTERNAL:
0374: * Check to see if this query already knows the return vale without preforming any further work.
0375: */
0376: public Object checkEarlyReturn(AbstractSession session,
0377: AbstractRecord translationRow) {
0378: return null;
0379: }
0380:
0381: /**
0382: * INTERNAL:
0383: * Check to see if a custom query should be used for this query.
0384: * This is done before the query is copied and prepared/executed.
0385: * null means there is none.
0386: */
0387: protected DatabaseQuery checkForCustomQuery(
0388: AbstractSession session, AbstractRecord translationRow) {
0389: return null;
0390: }
0391:
0392: /**
0393: * INTERNAL:
0394: * Check to see if this query needs to be prepare and prepare it.
0395: * The prepare is done on the original query to ensure that the work is not repeated.
0396: */
0397: public void checkPrepare(AbstractSession session,
0398: AbstractRecord translationRow) {
0399: // This query is first prepared for global common state, this must be synced.
0400: if (!isPrepared()) {// Avoid the monitor is already prepare, must check again for concurrency.
0401: // Prepared queries cannot be custom as then they would never have been prepared.
0402: synchronized (this ) {
0403: if (!isPrepared()) {
0404: // When custom SQL is used there is a possibility that the SQL contains the # token.
0405: // Avoid this by telling the call if this is custom SQL with parameters.
0406: // This must not be called for SDK calls.
0407: if ((isReadQuery() || isDataModifyQuery())
0408: && isCallQuery()
0409: && (getQueryMechanism() instanceof CallQueryMechanism)
0410: && ((translationRow == null) || translationRow
0411: .isEmpty())) {
0412: // Must check for read object queries as the row will be empty until the prepare.
0413: if (isReadObjectQuery() || isUserDefined()) {
0414: ((CallQueryMechanism) getQueryMechanism())
0415: .setCallHasCustomSQLArguments();
0416: }
0417: } else if (isCallQuery()
0418: && (getQueryMechanism() instanceof CallQueryMechanism)) {
0419: ((CallQueryMechanism) getQueryMechanism())
0420: .setCallHasCustomSQLArguments();
0421: }
0422: setSession(session);// Session is required for some init stuff.
0423: prepare();
0424: setSession(null);
0425: setIsPrepared(true);// MUST not set prepare until done as other thread may hit before finihsing the prepare.
0426: }
0427: }
0428: }
0429: }
0430:
0431: /**
0432: * INTERNAL:
0433: * Clone the query
0434: */
0435: public Object clone() {
0436: try {
0437: DatabaseQuery cloneQuery = (DatabaseQuery) super .clone();
0438:
0439: // partial fix for 3054240
0440: // need to pay attention to other components of the query, too MWN
0441: if (cloneQuery.properties != null) {
0442: if (cloneQuery.properties.isEmpty()) {
0443: cloneQuery.setProperties(null);
0444: } else {
0445: cloneQuery
0446: .setProperties((Hashtable) getProperties()
0447: .clone());
0448: }
0449: }
0450:
0451: // bug 3524620: now that the query mechanism is lazy-init'd,
0452: // only clone the query mechanism if we have one.
0453: if (hasQueryMechanism()) {
0454: cloneQuery.setQueryMechanism(getQueryMechanism().clone(
0455: cloneQuery));
0456: }
0457: cloneQuery.setIsPrepared(isPrepared());// Setting some things will trigger unprepare.
0458: return cloneQuery;
0459: } catch (CloneNotSupportedException e) {
0460: return null;
0461: }
0462: }
0463:
0464: /**
0465: * INTERNAL
0466: * Used to give the subclasses oportunity to copy aspects of the cloned query
0467: * to the original query.
0468: */
0469: protected void clonedQueryExecutionComplete(DatabaseQuery query,
0470: AbstractSession session) {
0471: //no-op for this class
0472: }
0473:
0474: /**
0475: * INTERNAL:
0476: * Convert all the class-name-based settings in this query to actual class-based
0477: * settings
0478: * This method is implemented by subclasses as necessary.
0479: * @param classLoader
0480: */
0481: public void convertClassNamesToClasses(ClassLoader classLoader) {
0482: // note: normally we would fix the argument types here, but they are already
0483: // lazily instantiated
0484: };
0485:
0486: /**
0487: * INTERNAL:
0488: * Added for backwards compatibility. shouldMaintainCache used to be tri-state and was converted to boolean.
0489: * This method is used by deployment XML to properly convert the tri-state variable to a boolean
0490: * Added for Bug 4034159
0491: */
0492: public void deploymentSetShouldMaintainCache(int maintainCache) {
0493: // FalseUndefinedTrue.Undefined is intentionally left ignored so it will map to the default.
0494: if (maintainCache == FalseUndefinedTrue.True) {
0495: setShouldMaintainCache(true);
0496: } else if (maintainCache == FalseUndefinedTrue.False) {
0497: setShouldMaintainCache(false);
0498: }
0499: }
0500:
0501: /**
0502: * INTERNAL:
0503: * Added for backwards compatibility. shouldMaintainCache used to be tri-state and was converted to boolean.
0504: * This method is used by deployment XML to properly convert the tri-state variable to a boolean
0505: * Added for Bug 4034159
0506: */
0507: public int deploymentShouldMaintainCache() {
0508: if (shouldMaintainCache()) {
0509: return FalseUndefinedTrue.True;
0510: } else {
0511: return FalseUndefinedTrue.False;
0512: }
0513: }
0514:
0515: /**
0516: * PUBLIC:
0517: * Do not Bind all arguments to any SQL statement.
0518: */
0519: public void dontBindAllParameters() {
0520: setShouldBindAllParameters(false);
0521: }
0522:
0523: /**
0524: * PUBLIC:
0525: * Dont cache the prepared statements, this requires full parameter binding as well.
0526: */
0527: public void dontCacheStatement() {
0528: setShouldCacheStatement(false);
0529: }
0530:
0531: /**
0532: * PUBLIC:
0533: * Do not cascade the query and its properties on the queries object(s) relationships.
0534: * This does not effect the queries private parts but only the object(s) direct row-level attributes.
0535: * This is the default for read queries and can be used in writting if it is known that only
0536: * row-level attributes changed, or to resolve circular foreign key dependencies.
0537: */
0538: public void dontCascadeParts() {
0539: setCascadePolicy(NoCascading);
0540: }
0541:
0542: /**
0543: * PUBLIC:
0544: * Set for the identity map (cache) to be ignored completely.
0545: * The cache check will be skipped and the result will not be put into the identity map.
0546: * This can be used to retreive the exact state of an object on the database.
0547: * By default the identity map is always maintained.
0548: */
0549: public void dontMaintainCache() {
0550: setShouldMaintainCache(false);
0551: }
0552:
0553: /**
0554: * INTERNAL:
0555: * Execute the query
0556: *
0557: * @exception DatabaseException - an error has occurred on the database.
0558: * @exception OptimisticLockException - an error has occurred using the optimistic lock feature.
0559: * @return - the result of executing the query.
0560: */
0561: public abstract Object executeDatabaseQuery()
0562: throws DatabaseException, OptimisticLockException;
0563:
0564: /**
0565: * INTERNAL:
0566: * Override query execution where Session is a UnitOfWork.
0567: * <p>
0568: * If there are objects in the cache return the results of the cache lookup.
0569: *
0570: * @param unitOfWork - the session in which the receiver will be executed.
0571: * @param translationRow - the arguments
0572: * @exception DatabaseException - an error has occurred on the database.
0573: * @exception OptimisticLockException - an error has occurred using the optimistic lock feature.
0574: * @return An object, the result of executing the query.
0575: */
0576: public Object executeInUnitOfWork(UnitOfWorkImpl unitOfWork,
0577: AbstractRecord translationRow) throws DatabaseException,
0578: OptimisticLockException {
0579: return execute(unitOfWork, translationRow);
0580: }
0581:
0582: /**
0583: * INTERNAL:
0584: * Execute the query. If there are objects in the cache return the results
0585: * of the cache lookup.
0586: *
0587: * @param session - the session in which the receiver will be executed.
0588: * @exception DatabaseException - an error has occurred on the database.
0589: * @exception OptimisticLockException - an error has occurred using the optimistic lock feature.
0590: * @return An object, the result of executing the query.
0591: */
0592: public Object execute(AbstractSession session,
0593: AbstractRecord translationRow) throws DatabaseException,
0594: OptimisticLockException {
0595: DatabaseQuery queryToExecute = this ;
0596:
0597: // Profile the query preparation time.
0598: session.startOperationProfile(SessionProfiler.QUERY_PREPARE);
0599:
0600: // This allows the query to check the cache or return early without doing any work.
0601: Object earlyReturn = queryToExecute.checkEarlyReturn(session,
0602: translationRow);
0603: if ((earlyReturn != null)
0604: || (isReadObjectQuery() && ((ReadObjectQuery) this )
0605: .shouldCheckCacheOnly())) {
0606: // Profile the query preparation time.
0607: session.endOperationProfile(SessionProfiler.QUERY_PREPARE);
0608: return earlyReturn;
0609: }
0610:
0611: boolean hasCustomQuery = false;
0612: if (!isPrepared() && shouldPrepare()) {
0613: // Prepared queries cannot be custom as then they would never have been prepared.
0614: DatabaseQuery customQuery = checkForCustomQuery(session,
0615: translationRow);
0616: if (customQuery != null) {
0617: hasCustomQuery = true;
0618: // The custom query will be used not the original.
0619: queryToExecute = customQuery;
0620: }
0621: }
0622:
0623: // Sometimes a session will clone the query and mutate the clone. If so
0624: // don't need to clone again.
0625: // All queries on a HistoricalSession become historical queries.
0626: // On a ServerSession bean-level pessimistic locking queries need to
0627: // be replaced with non-locking versions.
0628: boolean alreadyClonedQuery = false;
0629: DatabaseQuery sessionPreparedQuery = session
0630: .prepareDatabaseQuery(queryToExecute);
0631: if (sessionPreparedQuery != queryToExecute) {
0632: queryToExecute = sessionPreparedQuery;
0633: alreadyClonedQuery = true;
0634: }
0635:
0636: if (queryToExecute.shouldPrepare()) {
0637: queryToExecute.checkPrepare(session, translationRow);
0638: }
0639:
0640: // Then cloned for concurrency and repeatable execution.
0641: if (!alreadyClonedQuery) {
0642: queryToExecute = (DatabaseQuery) queryToExecute.clone();
0643: }
0644: queryToExecute.setTranslationRow(translationRow);
0645: // If the prepare has been disbale the clone is prepare dynamically to not parameterize the SQL.
0646: if (!queryToExecute.shouldPrepare()) {
0647: queryToExecute.checkPrepare(session, translationRow);
0648: }
0649: queryToExecute.setSession(session);
0650: if (hasCustomQuery) {
0651: prepareCustomQuery(queryToExecute);
0652: }
0653: queryToExecute.prepareForExecution();
0654:
0655: // Profile the query preparation time.
0656: session.endOperationProfile(SessionProfiler.QUERY_PREPARE);
0657:
0658: // Then executed.
0659: Object result = queryToExecute.executeDatabaseQuery();
0660:
0661: //give the subclasses the oportunity to retreive aspects of the cloned query
0662: clonedQueryExecutionComplete(queryToExecute, session);
0663: return result;
0664: }
0665:
0666: /**
0667: * INTERNAL:
0668: * Return the accessor.
0669: */
0670: public Accessor getAccessor() {
0671: return accessor;
0672: }
0673:
0674: /**
0675: * INTERNAL:
0676: * Return the arguments for use with the pre-defined query option
0677: */
0678: public Vector getArguments() {
0679: if (arguments == null) {
0680: arguments = oracle.toplink.essentials.internal.helper.NonSynchronizedVector
0681: .newInstance();
0682: }
0683: return arguments;
0684: }
0685:
0686: /**
0687: * INTERNAL:
0688: * Return the argumentTypes for use with the pre-defined query option
0689: */
0690: public Vector getArgumentTypes() {
0691: if ((argumentTypes == null) || argumentTypes.isEmpty()) {
0692: argumentTypes = new Vector();
0693: // Bug 3256198 - lazily initialize the argument types from their class names
0694: if (argumentTypeNames != null) {
0695: Iterator args = argumentTypeNames.iterator();
0696: while (args.hasNext()) {
0697: String argumentTypeName = (String) args.next();
0698: argumentTypes.addElement(Helper
0699: .getObjectClass(ConversionManager
0700: .loadClass(argumentTypeName)));
0701: }
0702: }
0703: }
0704: return argumentTypes;
0705: }
0706:
0707: /**
0708: * INTERNAL:
0709: * Return the argumentTypeNames for use with the pre-defined query option
0710: * These are used pre-initialization to construct the argumentTypes list.
0711: */
0712: public Vector getArgumentTypeNames() {
0713: if (argumentTypeNames == null) {
0714: argumentTypeNames = oracle.toplink.essentials.internal.helper.NonSynchronizedVector
0715: .newInstance();
0716: }
0717: return argumentTypeNames;
0718: }
0719:
0720: /**
0721: * INTERNAL:
0722: * Set the argumentTypes for use with the pre-defined query option
0723: */
0724: public void setArgumentTypes(Vector argumentTypes) {
0725: this .argumentTypes = argumentTypes;
0726: // bug 3256198 - ensure the list of type names matches the argument types.
0727: getArgumentTypeNames().clear();
0728: Iterator types = argumentTypes.iterator();
0729: while (types.hasNext()) {
0730: argumentTypeNames.addElement(((Class) types.next())
0731: .getName());
0732: }
0733: }
0734:
0735: /**
0736: * INTERNAL:
0737: * Set the argumentTypes for use with the pre-defined query option
0738: */
0739: public void setArgumentTypeNames(Vector argumentTypeNames) {
0740: this .argumentTypeNames = argumentTypeNames;
0741: }
0742:
0743: /**
0744: * INTERNAL:
0745: * Set the arguments for use with the pre-defined query option.
0746: * Maintain the argumentTypes as well.
0747: */
0748: public void setArguments(Vector arguments) {
0749: for (Enumeration enumtr = arguments.elements(); enumtr
0750: .hasMoreElements();) {
0751: // Maintain the argumentTypes as well
0752: addArgument((String) enumtr.nextElement());
0753: }
0754: }
0755:
0756: /**
0757: * INTERNAL:
0758: * Return the argumentValues for use with the
0759: * pre-defined query option
0760: */
0761: public Vector getArgumentValues() {
0762: if (argumentValues == null) {
0763: argumentValues = oracle.toplink.essentials.internal.helper.NonSynchronizedVector
0764: .newInstance();
0765: }
0766: return argumentValues;
0767: }
0768:
0769: /**
0770: * INTERNAL:
0771: * Return the argumentValues for use with the
0772: * pre-defined query option
0773: */
0774: public void setArgumentValues(Vector theArgumentValues) {
0775: argumentValues = theArgumentValues;
0776: }
0777:
0778: /**
0779: * INTERNAL:
0780: * Return the call for this query.
0781: * This call contains the SQL and argument list.
0782: * @see #getDatasourceCall()
0783: */
0784: public DatabaseCall getCall() {
0785: Call call = getDatasourceCall();
0786: if (call instanceof DatabaseCall) {
0787: return (DatabaseCall) call;
0788: } else {
0789: return null;
0790: }
0791: }
0792:
0793: /**
0794: * ADVANCED:
0795: * Return the call for this query.
0796: * This call contains the SQL and argument list.
0797: * @see #prepareCall(Session, DatabaseRow);
0798: */
0799: public Call getDatasourceCall() {
0800: Call call = null;
0801: if (getQueryMechanism() instanceof DatasourceCallQueryMechanism) {
0802: DatasourceCallQueryMechanism mechanism = (DatasourceCallQueryMechanism) getQueryMechanism();
0803: call = mechanism.getCall();
0804: // If has multiple calls return the first one.
0805: if (mechanism.hasMultipleCalls()) {
0806: call = (Call) mechanism.getCalls().get(0);
0807: }
0808: }
0809: if ((call == null)
0810: && getQueryMechanism().isEJBQLCallQueryMechanism()) {
0811: call = ((EJBQLCallQueryMechanism) getQueryMechanism())
0812: .getEJBQLCall();
0813: }
0814: return call;
0815: }
0816:
0817: /**
0818: * ADVANCED:
0819: * Return the calls for this query. This method can be called for queries with multiple calls
0820: * This call contains the SQL and argument list.
0821: * @see #prepareCall(Session, DatabaseRow);
0822: */
0823: public List getDatasourceCalls() {
0824: List calls = new Vector();
0825: if (getQueryMechanism() instanceof DatasourceCallQueryMechanism) {
0826: DatasourceCallQueryMechanism mechanism = (DatasourceCallQueryMechanism) getQueryMechanism();
0827:
0828: // If has multiple calls return the first one.
0829: if (mechanism.hasMultipleCalls()) {
0830: calls = mechanism.getCalls();
0831: } else {
0832: calls.add(mechanism.getCall());
0833: }
0834: }
0835: if ((calls.isEmpty())
0836: && getQueryMechanism().isEJBQLCallQueryMechanism()) {
0837: calls.add(((EJBQLCallQueryMechanism) getQueryMechanism())
0838: .getEJBQLCall());
0839: }
0840: return calls;
0841: }
0842:
0843: /**
0844: * INTERNAL:
0845: * Return the cascade policy.
0846: */
0847: public int getCascadePolicy() {
0848: return cascadePolicy;
0849: }
0850:
0851: /**
0852: * INTERNAL:
0853: * Return the descriptor assigned with the reference class
0854: */
0855: public ClassDescriptor getDescriptor() {
0856: return descriptor;
0857: }
0858:
0859: /**
0860: * PUBLIC:
0861: * Return the name of the query
0862: */
0863: public String getName() {
0864: return name;
0865: }
0866:
0867: /**
0868: * INTERNAL:
0869: * Property support for use by mappings.
0870: */
0871: public Hashtable getProperties() {
0872: if (properties == null) {//Lazy initialize to conserve space and allocation time.
0873: properties = new Hashtable(5);
0874: }
0875: return properties;
0876: }
0877:
0878: /**
0879: * INTERNAL:
0880: * Property support used by mappings to stach temporary stuff in the query.
0881: */
0882: public synchronized Object getProperty(Object property) {
0883: if (properties == null) {
0884: return null;
0885: }
0886: return getProperties().get(property);
0887: }
0888:
0889: /**
0890: * INTERNAL:
0891: * Return the mechanism assigned to the query
0892: */
0893: public DatabaseQueryMechanism getQueryMechanism() {
0894: // Bug 3524620 - lazy init
0895: if (queryMechanism == null) {
0896: queryMechanism = new ExpressionQueryMechanism(this );
0897: }
0898: return queryMechanism;
0899: }
0900:
0901: /**
0902: * INTERNAL:
0903: * Check if the mechanism has been set yet, used for lazy init.
0904: */
0905: public boolean hasQueryMechanism() {
0906: return (queryMechanism != null);
0907: }
0908:
0909: /**
0910: * PUBLIC:
0911: * Return the domain class associated with this query.
0912: * By default this is null, but should be overridden in subclasses.
0913: */
0914: public Class getReferenceClass() {
0915: return null;
0916: }
0917:
0918: /**
0919: * INTERNAL:
0920: * return the name of the reference class. Added for Mapping Workbench removal
0921: * of classpath dependancy. Overriden by subclasses.
0922: */
0923: public String getReferenceClassName() {
0924: return null;
0925: }
0926:
0927: /**
0928: * PUBLIC:
0929: * Return the selection criteria of the query.
0930: * This should only be used with expression queries, null will be returned for others.
0931: */
0932: public Expression getSelectionCriteria() {
0933: return getQueryMechanism().getSelectionCriteria();
0934: }
0935:
0936: /**
0937: * INTERNAL:
0938: * Return the current session.
0939: */
0940: public AbstractSession getSession() {
0941: return session;
0942: }
0943:
0944: /**
0945: * PUBLIC:
0946: * Return the name of the session that the query should be executed under.
0947: * This can be with the session broker to override the default session.
0948: */
0949: public String getSessionName() {
0950: return sessionName;
0951: }
0952:
0953: /**
0954: * PUBLIC:
0955: * Return the SQL statement of the query.
0956: * This can only be used with statement queries.
0957: */
0958: public SQLStatement getSQLStatement() {
0959: return ((StatementQueryMechanism) getQueryMechanism())
0960: .getSQLStatement();
0961: }
0962:
0963: /**
0964: * PUBLIC:
0965: * Return the SQL string of the query.
0966: * This can be used for SQL queries.
0967: * ADVANCED:
0968: * This can also be used for normal queries if they have been prepared, (i.e. query.prepareCall()).
0969: * @see #prepareCall(Session, DatabaseRow)
0970: */
0971: public String getEJBQLString() {
0972: if (!(getQueryMechanism().isEJBQLCallQueryMechanism())) {
0973: return null;
0974: }
0975: EJBQLCall call = (EJBQLCall) ((EJBQLCallQueryMechanism) getQueryMechanism())
0976: .getEJBQLCall();
0977: return call.getEjbqlString();
0978: }
0979:
0980: /**
0981: * PUBLIC:
0982: * Return the SQL string of the query.
0983: * This can be used for SQL queries.
0984: * ADVANCED:
0985: * This can also be used for normal queries if they have been prepared, (i.e. query.prepareCall()).
0986: * @see #prepareCall(Session, DatabaseRow)
0987: */
0988: public String getSQLString() {
0989: Call call = getDatasourceCall();
0990: if (call == null) {
0991: return null;
0992: }
0993: if (!(call instanceof SQLCall)) {
0994: return null;
0995: }
0996:
0997: return ((SQLCall) call).getSQLString();
0998: }
0999:
1000: /**
1001: * PUBLIC:
1002: * Return the SQL strings of the query. Used for queries with multiple calls
1003: * This can be used for SQL queries.
1004: * ADVANCED:
1005: * This can also be used for normal queries if they have been prepared, (i.e. query.prepareCall()).
1006: * @see #prepareCall(Session, DatabaseRow)
1007: */
1008: public List getSQLStrings() {
1009: List calls = getDatasourceCalls();
1010: if ((calls == null) || calls.isEmpty()) {
1011: return null;
1012: }
1013: Vector returnSQL = new Vector(calls.size());
1014: Iterator iterator = calls.iterator();
1015: while (iterator.hasNext()) {
1016: Call call = (Call) iterator.next();
1017: if (!(call instanceof SQLCall)) {
1018: return null;
1019: }
1020: returnSQL.addElement(((SQLCall) call).getSQLString());
1021: }
1022: return returnSQL;
1023: }
1024:
1025: /**
1026: * INTERNAL:
1027: * Returns the internal tri-state calue of shouldBindParameters
1028: * used far cascading these settings
1029: */
1030: public int getShouldBindAllParameters() {
1031: return this .shouldBindAllParameters;
1032: }
1033:
1034: /**
1035: * ADVANCED:
1036: * This can be used to access a queries translated SQL if they have been prepared, (i.e. query.prepareCall()).
1037: * The Record argument is one of (DatabaseRow, XMLRecord) that contains the query arguments.
1038: * @see #prepareCall(oracle.toplink.essentials.sessions.Session, Record)
1039: */
1040: public String getTranslatedSQLString(
1041: oracle.toplink.essentials.sessions.Session session,
1042: Record translationRow) {
1043: //CR#2859559 fix to use Session and Record interfaces not impl classes.
1044: CallQueryMechanism queryMechanism = (CallQueryMechanism) getQueryMechanism();
1045: if (queryMechanism.getCall() == null) {
1046: return null;
1047: }
1048: SQLCall call = (SQLCall) queryMechanism.getCall().clone();
1049: call.translate((AbstractRecord) translationRow, queryMechanism
1050: .getModifyRow(), (AbstractSession) session);
1051: return call.getSQLString();
1052: }
1053:
1054: /**
1055: * ADVANCED:
1056: * This can be used to access a queries translated SQL if they have been prepared, (i.e. query.prepareCall()).
1057: * This method can be used for queries with multiple calls.
1058: * @see #prepareCall(Session, DatabaseRow)
1059: */
1060: public List getTranslatedSQLStrings(
1061: oracle.toplink.essentials.sessions.Session session,
1062: Record translationRow) {
1063: CallQueryMechanism queryMechanism = (CallQueryMechanism) getQueryMechanism();
1064: if ((queryMechanism.getCalls() == null)
1065: || queryMechanism.getCalls().isEmpty()) {
1066: return null;
1067: }
1068: Vector calls = new Vector(queryMechanism.getCalls().size());
1069: Iterator iterator = queryMechanism.getCalls().iterator();
1070: while (iterator.hasNext()) {
1071: SQLCall call = (SQLCall) iterator.next();
1072: call = (SQLCall) call.clone();
1073: call.translate((AbstractRecord) translationRow,
1074: queryMechanism.getModifyRow(),
1075: (AbstractSession) session);
1076: calls.addElement(call.getSQLString());
1077: }
1078: return calls;
1079: }
1080:
1081: /**
1082: * INTERNAL:
1083: * Return the row for translation
1084: */
1085: public AbstractRecord getTranslationRow() {
1086: return translationRow;
1087: }
1088:
1089: /**
1090: * INTERNAL:
1091: * returns true if the accessor has already been set. The getAccessor() will attempt to
1092: * lazily initialzie it.
1093: */
1094: public boolean hasAccessor() {
1095: return accessor != null;
1096: }
1097:
1098: /**
1099: * INTERNAL:
1100: * Return if any properties exist in the query.
1101: */
1102: public boolean hasProperties() {
1103: return (properties != null) && (!properties.isEmpty());
1104: }
1105:
1106: /**
1107: * PUBLIC:
1108: * Return if a name of the session that the query should be executed under has been specified.
1109: * This can be with the session broker to override the default session.
1110: */
1111: public boolean hasSessionName() {
1112: return sessionName != null;
1113: }
1114:
1115: /**
1116: * PUBLIC:
1117: * Session's shouldBindAllParameters() defines whether to bind or not
1118: * (default setting)
1119: */
1120: public void ignoreBindAllParameters() {
1121: this .shouldBindAllParameters = Undefined;
1122: }
1123:
1124: /**
1125: * PUBLIC:
1126: * Session's shouldCacheAllStatements() defines whether to cache or not
1127: * (default setting)
1128: */
1129: public void ignoreCacheStatement() {
1130: this .shouldCacheStatement = Undefined;
1131: }
1132:
1133: /**
1134: * PUBLIC:
1135: * Return true if this query uses an SQL or stored procedure, or SDK call.
1136: */
1137: public boolean isCallQuery() {
1138: return getQueryMechanism().isCallQueryMechanism();
1139: }
1140:
1141: /**
1142: * INTERNAL:
1143: * Returns true if this query has been created as the result of cascading a delete of an aggregate collection
1144: * in a UnitOfWork
1145: * CR 2811
1146: */
1147: public boolean isCascadeOfAggregateDelete() {
1148: return getCascadePolicy() == CascadeAggregateDelete;
1149: }
1150:
1151: /**
1152: * PUBLIC:
1153: * Return if this is a data modify query.
1154: */
1155: public boolean isDataModifyQuery() {
1156: return false;
1157: }
1158:
1159: /**
1160: * PUBLIC:
1161: * Return if this is a data read query.
1162: */
1163: public boolean isDataReadQuery() {
1164: return false;
1165: }
1166:
1167: /**
1168: * PUBLIC:
1169: * Return if this is a delete all query.
1170: */
1171: public boolean isDeleteAllQuery() {
1172: return false;
1173: }
1174:
1175: /**
1176: * PUBLIC:
1177: * Return if this is a delete object query.
1178: */
1179: public boolean isDeleteObjectQuery() {
1180: return false;
1181: }
1182:
1183: /**
1184: * PUBLIC:
1185: * Return true if this query uses an expression query mechanism
1186: */
1187: public boolean isExpressionQuery() {
1188: return getQueryMechanism().isExpressionQueryMechanism();
1189: }
1190:
1191: /**
1192: * PUBLIC:
1193: * Return true if this is a modify all query.
1194: */
1195: public boolean isModifyAllQuery() {
1196: return false;
1197: }
1198:
1199: /**
1200: * PUBLIC:
1201: * Return true if this is a modify query.
1202: */
1203: public boolean isModifyQuery() {
1204: return false;
1205: }
1206:
1207: /**
1208: * PUBLIC:
1209: * Return true if this is an update all query.
1210: */
1211: public boolean isUpdateAllQuery() {
1212: return false;
1213: }
1214:
1215: /**
1216: * PUBLIC:
1217: * Return true if this is an update object query.
1218: */
1219: public boolean isUpdateObjectQuery() {
1220: return false;
1221: }
1222:
1223: /**
1224: * PUBLIC:
1225: * If executed against a RepeatableWriteUnitOfWork if this attribute is true
1226: * TopLink will write changes to the database before executing the query.
1227: */
1228: public Boolean getFlushOnExecute() {
1229: return this .flushOnExecute;
1230: }
1231:
1232: /**
1233: * PUBLIC:
1234: * Return true if this is an insert object query.
1235: */
1236: public boolean isInsertObjectQuery() {
1237: return false;
1238: }
1239:
1240: /**
1241: * PUBLIC:
1242: * Return true if this is an object level modify query.
1243: */
1244: public boolean isObjectLevelModifyQuery() {
1245: return false;
1246: }
1247:
1248: /**
1249: * PUBLIC:
1250: * Return true if this is an object level read query.
1251: */
1252: public boolean isObjectLevelReadQuery() {
1253: return false;
1254: }
1255:
1256: /**
1257: * PUBLIC:
1258: * Return if this is an object building query.
1259: */
1260: public boolean isObjectBuildingQuery() {
1261: return true;
1262: }
1263:
1264: /**
1265: * INTERNAL:
1266: * Queries are prepared when they are executed and then do not need to be
1267: * prepared on subsequent executions. This method returns true if this
1268: * query has been prepared. Updating the settings on a query will 'un-prepare'
1269: * the query.
1270: */
1271: public boolean isPrepared() {
1272: return isPrepared;
1273: }
1274:
1275: /**
1276: * PUBLIC:
1277: * Return true if this is a read all query.
1278: */
1279: public boolean isReadAllQuery() {
1280: return false;
1281: }
1282:
1283: /**
1284: * PUBLIC:
1285: * Return ture if this is a read object query.
1286: */
1287: public boolean isReadObjectQuery() {
1288: return false;
1289: }
1290:
1291: /**
1292: * PUBLIC:
1293: * Return true if this is a read query.
1294: */
1295: public boolean isReadQuery() {
1296: return false;
1297: }
1298:
1299: /**
1300: * PUBLIC:
1301: * Return true if this is a report query.
1302: */
1303: public boolean isReportQuery() {
1304: return false;
1305: }
1306:
1307: /**
1308: * PUBLIC:
1309: * Return true if this query uses an SQL query mechanism .
1310: */
1311: public boolean isSQLCallQuery() {
1312: // BUG#2669342 CallQueryMechanism and isCallQueryMechanism have different meaning as SDK return true but isn't.
1313: Call call = getDatasourceCall();
1314: return (call != null) && (call instanceof SQLCall);
1315: }
1316:
1317: /**
1318: * INTERNAL:
1319: * Return true if the query is a custom user defined query.
1320: */
1321: public boolean isUserDefined() {
1322: return isUserDefined;
1323: }
1324:
1325: /**
1326: * PUBLIC:
1327: * Return true if this is a write object query.
1328: */
1329: public boolean isWriteObjectQuery() {
1330: return false;
1331: }
1332:
1333: /**
1334: * PUBLIC:
1335: * Set for the identity map (cache) to be maintained.
1336: * This is the default.
1337: */
1338: public void maintainCache() {
1339: setShouldMaintainCache(true);
1340: }
1341:
1342: /**
1343: * INTERNAL:
1344: * This is different from 'prepareForExecution' in that this is called on the original query,
1345: * and the other is called on the copy of the query.
1346: * This query is copied for concurrency so this prepare can only setup things that
1347: * will apply to any future execution of this query.
1348: *
1349: * Resolve the queryTimeout using the DescriptorQueryManager if required.
1350: */
1351: protected void prepare() throws QueryException {
1352: getQueryMechanism().prepare();
1353: }
1354:
1355: /**
1356: * ADVANCED:
1357: * Pre-generate the call/SQL for the query.
1358: * This method takes a Session and an implementor of Record (DatebaseRow or XMLRecord).
1359: * This can be used to access the SQL for a query without executing it.
1360: * To access the call use, query.getCall(), or query.getSQLString() for the SQL.
1361: * Note the SQL will have argument markers in it (i.e. "?").
1362: * To translate these use query.getTranslatedSQLString(session, translationRow).
1363: * @see #getCall()
1364: * @see #getSQLString()
1365: * @see #getTranslatedSQLString(oracle.toplink.essentials.sessions.Session, Record)
1366: */
1367: public void prepareCall(
1368: oracle.toplink.essentials.sessions.Session session,
1369: Record translationRow) throws QueryException {
1370: //CR#2859559 fix to use Session and Record interfaces not impl classes.
1371: checkPrepare((AbstractSession) session,
1372: (AbstractRecord) translationRow);
1373: }
1374:
1375: /**
1376: * INTERNAL:
1377: * Set the properties needed to be cascaded into the custom query.
1378: */
1379: protected void prepareCustomQuery(DatabaseQuery customQuery) {
1380: // Nothing by default.
1381: }
1382:
1383: /**
1384: * INTERNAL:
1385: * Prepare the receiver for execution in a session. In particular,
1386: * set the descriptor of the receiver to the Descriptor for the
1387: * appropriate class for the receiver's object.
1388: */
1389: public void prepareForExecution() throws QueryException {
1390: getQueryMechanism().prepareForExecution();
1391: }
1392:
1393: protected void prepareForRemoteExecution() {
1394: ;
1395: }
1396:
1397: /**
1398: * INTERNAL:
1399: * Property support used by mappings.
1400: */
1401: public void removeProperty(Object property) {
1402: getProperties().remove(property);
1403: }
1404:
1405: /**
1406: * INTERNAL:
1407: * Translate argumentValues into a database row.
1408: */
1409: public AbstractRecord rowFromArguments(Vector argumentValues)
1410: throws QueryException {
1411: Vector argumentNames = getArguments();
1412:
1413: if (argumentNames.size() != argumentValues.size()) {
1414: throw QueryException
1415: .argumentSizeMismatchInQueryAndQueryDefinition(this );
1416: }
1417:
1418: AbstractRecord row = new DatabaseRecord();
1419: for (int index = 0; index < argumentNames.size(); index++) {
1420: String argumentName = (String) argumentNames
1421: .elementAt(index);
1422: Object argumentValue = argumentValues.elementAt(index);
1423: row.put(new DatabaseField(argumentName), argumentValue);
1424: }
1425:
1426: return row;
1427: }
1428:
1429: /**
1430: * INTERNAL:
1431: * Set the accessor, the query must always use the same accessor for database access.
1432: * This is required to support connection pooling.
1433: */
1434: public void setAccessor(Accessor accessor) {
1435: this .accessor = accessor;
1436: }
1437:
1438: /**
1439: * PUBLIC:
1440: * Used to define a store procedure or SQL query.
1441: */
1442: public void setDatasourceCall(Call call) {
1443: if (call == null) {
1444: return;
1445: }
1446: setQueryMechanism(call.buildNewQueryMechanism(this ));
1447: }
1448:
1449: /**
1450: * PUBLIC:
1451: * Used to define a store procedure or SQL query.
1452: */
1453: public void setCall(Call call) {
1454: setDatasourceCall(call);
1455: }
1456:
1457: /**
1458: * INTERNAL:
1459: * Set the cascade policy.
1460: */
1461: public void setCascadePolicy(int policyConstant) {
1462: cascadePolicy = policyConstant;
1463: }
1464:
1465: /**
1466: * INTERNAL:
1467: * Set the descriptor for the query.
1468: */
1469: public void setDescriptor(ClassDescriptor descriptor) {
1470: // If the descriptor changed must unprepare as the SQL may change.
1471: if (this .descriptor != descriptor) {
1472: setIsPrepared(false);
1473: }
1474: this .descriptor = descriptor;
1475: }
1476:
1477: /**
1478: * PUBLIC:
1479: * To any user of this object. Set the EJBQL string of the query.
1480: * If arguments are required in the string they will be preceeded by "?" then the argument number.
1481: */
1482: public void setEJBQLString(String ejbqlString) {
1483: //Added the check for when we are building the query from the deployment XML
1484: if ((ejbqlString != null) && (!ejbqlString.equals(""))) {
1485: EJBQLCallQueryMechanism mechanism = new EJBQLCallQueryMechanism(
1486: this , new EJBQLCall(ejbqlString));
1487: setQueryMechanism(mechanism);
1488: }
1489: }
1490:
1491: /**
1492: * PUBLIC:
1493: * If executed against a RepeatableWriteUnitOfWork if this attribute is true
1494: * TopLink will write changes to the database before executing the query.
1495: */
1496: public void setFlushOnExecute(Boolean flushMode) {
1497: this .flushOnExecute = flushMode;
1498: }
1499:
1500: /**
1501: * INTERNAL:
1502: * If changes are made to the query that affect the derived SQL or Call
1503: * parameters the query needs to be prepared again.
1504: * <p>
1505: * Automatically called internally.
1506: */
1507: public void setIsPrepared(boolean isPrepared) {
1508: this .isPrepared = isPrepared;
1509: }
1510:
1511: /**
1512: * INTERNAL:
1513: * Set if the query is a custom user defined query.
1514: */
1515: public void setIsUserDefined(boolean isUserDefined) {
1516: this .isUserDefined = isUserDefined;
1517: }
1518:
1519: /**
1520: * PUBLIC:
1521: * Set the query's name.
1522: * Queries can be named and added to a descriptor or the session and then referenced by name.
1523: */
1524: public void setName(String queryName) {
1525: name = queryName;
1526: }
1527:
1528: /**
1529: * INTERNAL:
1530: * Property support used by mappings.
1531: */
1532: public void setProperties(Hashtable properties) {
1533: this .properties = properties;
1534: }
1535:
1536: /**
1537: * INTERNAL:
1538: * Property support used by mappings to stache temporary stuff.
1539: */
1540: public synchronized void setProperty(Object property, Object value) {
1541: getProperties().put(property, value);
1542: }
1543:
1544: /**
1545: * Set the query mechanism for the query.
1546: */
1547: protected void setQueryMechanism(
1548: DatabaseQueryMechanism queryMechanism) {
1549: this .queryMechanism = queryMechanism;
1550: // Must un-prepare is prepare as the SQL may change.
1551: setIsPrepared(false);
1552: }
1553:
1554: /**
1555: * PUBLIC:
1556: * To any user of this object. Set the selection criteria of the query.
1557: * This method be used when dealing with expressions.
1558: */
1559: public void setSelectionCriteria(Expression expression) {
1560: // Do not overwrite the call if the expression is null.
1561: if ((expression == null)
1562: && (!getQueryMechanism().isExpressionQueryMechanism())) {
1563: return;
1564: }
1565: if (!getQueryMechanism().isExpressionQueryMechanism()) {
1566: setQueryMechanism(new ExpressionQueryMechanism(this ,
1567: expression));
1568: } else {
1569: ((ExpressionQueryMechanism) getQueryMechanism())
1570: .setSelectionCriteria(expression);
1571: }
1572:
1573: // Must un-prepare is prepare as the SQL may change.
1574: setIsPrepared(false);
1575: }
1576:
1577: /**
1578: * INTERNAL:
1579: * Set the session for the query
1580: */
1581: public void setSession(AbstractSession session) {
1582: this .session = session;
1583: }
1584:
1585: /**
1586: * PUBLIC:
1587: * Set the name of the session that the query should be executed under.
1588: * This can be with the session broker to override the default session.
1589: */
1590: public void setSessionName(String sessionName) {
1591: this .sessionName = sessionName;
1592: }
1593:
1594: /**
1595: * PUBLIC:
1596: * Bind all arguments to any SQL statement.
1597: */
1598: public void setShouldBindAllParameters(
1599: boolean shouldBindAllParameters) {
1600: if (shouldBindAllParameters) {
1601: this .shouldBindAllParameters = True;
1602: } else {
1603: this .shouldBindAllParameters = False;
1604: }
1605: setIsPrepared(false);
1606: }
1607:
1608: /**
1609: * INTERNAL:
1610: * Sets the internal tri-state value of shouldBindAllParams
1611: * Used to cascade this value to alther queries
1612: */
1613: public void setShouldBindAllParameters(int bindAllParams) {
1614: this .shouldBindAllParameters = bindAllParams;
1615: }
1616:
1617: /**
1618: * PUBLIC:
1619: * Cache the prepared statements, this requires full parameter binding as well.
1620: */
1621: public void setShouldCacheStatement(boolean shouldCacheStatement) {
1622: if (shouldCacheStatement) {
1623: this .shouldCacheStatement = True;
1624: } else {
1625: this .shouldCacheStatement = False;
1626: }
1627: setIsPrepared(false);
1628: }
1629:
1630: /**
1631: * PUBLIC:
1632: * Set if the identity map (cache) should be used or not.
1633: * If not the cache check will be skipped and the result will not be put into the identity map.
1634: * By default the identity map is always maintained.
1635: */
1636: public void setShouldMaintainCache(boolean shouldMaintainCache) {
1637: this .shouldMaintainCache = shouldMaintainCache;
1638: }
1639:
1640: /**
1641: * PUBLIC:
1642: * Set if the query should be prepared.
1643: * TopLink automatically prepares queries to generate their SQL only once,
1644: * one each execution of the query the SQL does not need to be generated again only the arguments need to be translated.
1645: * This option is provide to disable this optimization as in can cause problems with certain types of queries that require dynamic SQL basd on their arguments.
1646: * <p>These queries include:
1647: * <ul>
1648: * <li> Expressions that make use of 'equal' where the argument value has the potential to be null, this can cause problems on databases that require IS NULL, instead of = NULL.
1649: * <li> Expressions that make use of 'in' and that use parameter binding, this will cause problems as the in values must be bound individually.
1650: * </ul>
1651: */
1652: public void setShouldPrepare(boolean shouldPrepare) {
1653: this .shouldPrepare = shouldPrepare;
1654: setIsPrepared(false);
1655: }
1656:
1657: /**
1658: * ADVANCED:
1659: * The wrapper policy can be enable on a query.
1660: */
1661: public void setShouldUseWrapperPolicy(boolean shouldUseWrapperPolicy) {
1662: this .shouldUseWrapperPolicy = shouldUseWrapperPolicy;
1663: }
1664:
1665: /**
1666: * PUBLIC:
1667: * To any user of this object. Set the SQL statement of the query.
1668: * This method should only be used when dealing with statement objects.
1669: */
1670: public void setSQLStatement(SQLStatement sqlStatement) {
1671: setQueryMechanism(new StatementQueryMechanism(this ,
1672: sqlStatement));
1673: }
1674:
1675: /**
1676: * PUBLIC:
1677: * To any user of this object. Set the SQL string of the query.
1678: * This method should only be used when dealing with user defined SQL strings.
1679: * If arguments are required in the string they will be preceeded by "#" then the argument name.
1680: */
1681: public void setSQLString(String sqlString) {
1682: //Added the check for when we are building the query from the deployment XML
1683: if ((sqlString != null) && (!sqlString.equals(""))) {
1684: setCall(new SQLCall(sqlString));
1685: }
1686: }
1687:
1688: /**
1689: * INTERNAL:
1690: * Set the row for translation
1691: */
1692: public void setTranslationRow(AbstractRecord translationRow) {
1693: this .translationRow = translationRow;
1694: }
1695:
1696: /**
1697: * PUBLIC:
1698: * Bind all arguments to any SQL statement.
1699: */
1700: public boolean shouldBindAllParameters() {
1701: return shouldBindAllParameters == True;
1702: }
1703:
1704: /**
1705: * PUBLIC:
1706: * Cache the prepared statements, this requires full parameter binding as well.
1707: */
1708: public boolean shouldCacheStatement() {
1709: return shouldCacheStatement == True;
1710: }
1711:
1712: /**
1713: * PUBLIC:
1714: * Flag used to determine if all parts should be cascaded
1715: */
1716: public boolean shouldCascadeAllParts() {
1717: return getCascadePolicy() == CascadeAllParts;
1718: }
1719:
1720: /**
1721: * PUBLIC:
1722: * Mappings should be checked to determined if the current operation should be
1723: * cascaded to the objects referenced.
1724: */
1725: public boolean shouldCascadeByMapping() {
1726: return getCascadePolicy() == CascadeByMapping;
1727: }
1728:
1729: /**
1730: * INTERNAL:
1731: * Flag used for unit of works cascade policy.
1732: */
1733: public boolean shouldCascadeOnlyDependentParts() {
1734: return getCascadePolicy() == CascadeDependentParts;
1735: }
1736:
1737: /**
1738: * PUBLIC:
1739: * Flag used to determine if any parts should be cascaded
1740: */
1741: public boolean shouldCascadeParts() {
1742: return getCascadePolicy() != NoCascading;
1743: }
1744:
1745: /**
1746: * PUBLIC:
1747: * Flag used to determine if any private parts should be cascaded
1748: */
1749: public boolean shouldCascadePrivateParts() {
1750: return (getCascadePolicy() == CascadePrivateParts)
1751: || (getCascadePolicy() == CascadeAllParts);
1752: }
1753:
1754: /**
1755: * INTERNAL:
1756: * Flag used to determine if the call needs to be cloned.
1757: */
1758: public boolean shouldCloneCall() {
1759: return shouldCloneCall;
1760: }
1761:
1762: /**
1763: * PUBLIC:
1764: * Local shouldBindAllParameters() should be ignored,
1765: * Session's shouldBindAllParameters() should be used.
1766: */
1767: public boolean shouldIgnoreBindAllParameters() {
1768: return shouldBindAllParameters == Undefined;
1769: }
1770:
1771: /**
1772: * PUBLIC:
1773: * Local shouldCacheStatement() should be ignored,
1774: * Session's shouldCacheAllStatements() should be used.
1775: */
1776: public boolean shouldIgnoreCacheStatement() {
1777: return shouldCacheStatement == Undefined;
1778: }
1779:
1780: /**
1781: * PUBLIC:
1782: * Return if the identity map (cache) should be used or not.
1783: * If not the cache check will be skipped and the result will not be put into the identity map.
1784: * By default the identity map is always maintained.
1785: */
1786: public boolean shouldMaintainCache() {
1787: return shouldMaintainCache;
1788: }
1789:
1790: /**
1791: * PUBLIC:
1792: * Return if the query should be prepared.
1793: * TopLink automatically prepares queries to generate their SQL only once,
1794: * one each execution of the query the SQL does not need to be generated again only the arguments need to be translated.
1795: * This option is provide to disable this optimization as in can cause problems with certain types of queries that require dynamic SQL basd on their arguments.
1796: * <p>These queries include:
1797: * <ul>
1798: * <li> Expressions that make use of 'equal' where the argument value has the potential to be null, this can cause problems on databases that require IS NULL, instead of = NULL.
1799: * <li> Expressions that make use of 'in' and that use parameter binding, this will cause problems as the in values must be bound individually.
1800: * </ul>
1801: */
1802: public boolean shouldPrepare() {
1803: return shouldPrepare;
1804: }
1805:
1806: /**
1807: * ADVANCED:
1808: * The wrapper policy can be enabled on a query.
1809: */
1810: public boolean shouldUseWrapperPolicy() {
1811: return shouldUseWrapperPolicy;
1812: }
1813:
1814: public String toString() {
1815: return Helper.getShortClassName(getClass()) + "()";
1816: }
1817: }
|