FileDocCategorySizeDatePackage
ReportQuery.javaAPI DocGlassfish v2 API52952Thu May 31 11:09:30 BST 2007oracle.toplink.essentials.queryframework

ReportQuery

public class ReportQuery extends ReadAllQuery
Purpose: Query for information about a set of objects instead of the objects themselves. This supports select single attributes, nested attributes, aggregation functions and group bys.

Attribute Types:

  1. addAttribute("directQueryKey") is a short cut method to add an attribute with the same name as its corresponding direct query key.
  2. addAttribute("attributeName", expBuilder.get("oneToOneMapping").get("directQueryKey")) is the full approach for get values through joined 1:1 relationships.
  3. addAttribute("attributeName", expBuilder.getField("TABLE.FIELD")) allows the addition of raw values or values which were not mapped in the object model directly (i.e. FK attributes).
  4. addAttribute("attributeName", null) Leave a place holder (NULL) value in the result (used for included values from other systems or calculated values).
Retrieving Primary Keys: It is possble to retrieve the primary key raw values within each result, but stored in a separate (internal) vector. This primary key vector can later be used to retrieve the real object.
see
#retrievePrimaryKeys()
see
ReportQueryResult#readObject(Class, Session) If the values are wanted in the result array then they must be added as attributes. For primary keys which are not mapped directly you can add them as DatabaseFields (see above).
author
Doug Clarke
since
TOPLink/Java 2.0

Fields Summary
public static final int
ShouldReturnSingleResult
Simplifies the result by only returning the first result.
public static final int
ShouldReturnSingleValue
Simplifies the result by only returning one value.
public static final int
ShouldReturnSingleAttribute
Simplifies the result by only returning the single attribute(as opposed to wrapping in a ReportQueryResult).
public static final int
ShouldReturnWithoutReportQueryResult
For EJB 3 support returns results without using the ReportQueryResult
public static final int
FULL_PRIMARY_KEY
Specifies whether to retreive primary keys, first primary key, or no primary key.
public static final int
FIRST_PRIMARY_KEY
public static final int
NO_PRIMARY_KEY
protected static final Boolean
RESULT_IGNORED
protected int
shouldRetrievePrimaryKeys
Flag indicating wether the primary key values should also be retrieved for the reference class.
protected Vector
names
Collection of names for use by results.
protected Vector
items
Items to be selected, these could be attributes or aggregate functions.
protected Vector
groupByExpressions
Expressions representing fields to be used in the GROUP BY clause.
protected Expression
havingExpression
Expression representing the HAVING clause.
protected int
returnChoice
Can be one of (ShouldReturnSingleResult, ShouldReturnSingleValue, ShouldReturnSingleAttribute) Simplifies the result by only returning the first result, first value, or all attribute values
protected boolean
addToConstructorItem
flag to allow items to be added to the last ConstructorReportItem
protected Class
resultConstructorClass
protected Class[]
constructorArgTypes
protected List
constructorMappings
protected HashSet
returnedKeys
Constructors Summary
public ReportQuery()
INTERNAL: The builder should be provided.


               
      
        this.queryMechanism = new ExpressionQueryMechanism(this);
        this.items = new Vector();
        this.shouldRetrievePrimaryKeys = NO_PRIMARY_KEY;
        this.groupByExpressions = new Vector(3);
        this.havingExpression=null;
        this.addToConstructorItem = false;

        // overwrite the lock mode to NO_LOCK, this prevents the report query to lock
        // when DEFAULT_LOCK_MODE and a pessimistic locking policy are used.
        this.setLockMode(ObjectBuildingQuery.NO_LOCK);
    
public ReportQuery(Class javaClass, Expression expression)

        this();
        this.defaultBuilder = expression.getBuilder();
        setReferenceClass(javaClass);
        setSelectionCriteria(expression);
    
public ReportQuery(Class javaClass, ExpressionBuilder builder)
PUBLIC: The report query is require to be constructor with an expression builder. This build must be used for the selection critiera, any item expressions, group bys and order bys.

        this();
        this.defaultBuilder = builder;
        setReferenceClass(javaClass);
    
public ReportQuery(ExpressionBuilder builder)
PUBLIC: The report query is require to be constructor with an expression builder. This build must be used for the selection critiera, any item expressions, group bys and order bys.

        this();
        this.defaultBuilder = builder;
    
Methods Summary
public voidaddAttribute(java.lang.String itemName)
PUBLIC: Add the attribute from the reference class to be included in the result. EXAMPLE: reportQuery.addAttribute("firstName");

        addItem(itemName, getExpressionBuilder().get(itemName));
    
public voidaddAttribute(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression)
PUBLIC: Add the attribute to be included in the result. EXAMPLE: reportQuery.addAttribute("city", expBuilder.get("address").get("city"));

        addItem(itemName, attributeExpression);
    
public voidaddAttribute(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression, java.lang.Class type)
PUBLIC: Add the attribute to be included in the result. Return the result as the provided class EXAMPLE: reportQuery.addAttribute("city", expBuilder.get("period").get("startTime"), Time.class);

        addItem(itemName, attributeExpression, type);
    
public voidaddAverage(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression)
PUBLIC: Add the average value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addAverage("managerSalary", expBuilder.get("manager").get("salary"));

        addItem(itemName, attributeExpression.average());
    
public voidaddAverage(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression, java.lang.Class resultType)
PUBLIC: Add the average value of the attribute to be included in the result and return it as the specified resultType. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addAverage("managerSalary", expBuilder.get("manager").get("salary"), Double.class);

        addItem(itemName, attributeExpression.average(), resultType);
    
public voidaddAverage(java.lang.String itemName)
PUBLIC: Add the average value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addAverage("salary");

        addAverage(itemName, getExpressionBuilder().get(itemName));
    
public voidaddAverage(java.lang.String itemName, java.lang.Class resultType)
PUBLIC: Add the average value of the attribute to be included in the result and return it as the specified resultType. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addAverage("salary", Float.class);

        addAverage(itemName, getExpressionBuilder().get(itemName), resultType);
    
public voidaddConstructorReportItem(oracle.toplink.essentials.queryframework.ConstructorReportItem item)
PUBLIC: Add a ConstructorReportItem to this query's set of return values.

param
ConstructorReportItem - used to specify a class constructor and values to pass in from this query
see
ConstructorReportItem

        addItem(item);
    
public voidaddCount()
PUBLIC: Include the number of rows returned by the query in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: Java: reportQuery.addCount(); SQL: SELECT COUNT (*) FROM ...

see
#addCount(java.lang.String)

        addCount("COUNT", getExpressionBuilder());
    
public voidaddCount(java.lang.String attributeName)
PUBLIC: Include the number of rows returned by the query in the result, where attributeExpression is not null. Aggregation functions can be used with a group by, or on the entire result set.

Example:

TopLink: reportQuery.addCount("id"); SQL: SELECT COUNT (t0.EMP_ID) FROM EMPLOYEE t0, ...

param
attributeName the number of rows where attributeName is not null will be returned.
see
#addCount(java.lang.String, oracle.toplink.essentials.expressions.Expression)

        addCount(attributeName, getExpressionBuilder().get(attributeName));
    
public voidaddCount(java.lang.String attributeName, java.lang.Class resultType)
PUBLIC: Include the number of rows returned by the query in the result, where attributeExpression is not null. Aggregation functions can be used with a group by, or on the entire result set. Set the count to be returned as the specified resultType.

Example:

TopLink: reportQuery.addCount("id", Long.class); SQL: SELECT COUNT (t0.EMP_ID) FROM EMPLOYEE t0, ...

param
attributeName the number of rows where attributeName is not null will be returned.
see
#addCount(java.lang.String, oracle.toplink.essentials.expressions.Expression)

        addCount(attributeName, getExpressionBuilder().get(attributeName), resultType);
    
public voidaddCount(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression)
PUBLIC: Include the number of rows returned by the query in the result, where attributeExpression is not null. Aggregation functions can be used with a group by, or on the entire result set.

Example:

TopLink: reportQuery.addCount("Count", getExpressionBuilder().get("id")); SQL: SELECT COUNT (t0.EMP_ID) FROM EMPLOYEE t0, ...

Example: counting only distinct values of an attribute.

TopLink: reportQuery.addCount("Count", getExpressionBuilder().get("address").distinct()); SQL: SELECT COUNT (DISTINCT t0.ADDR_ID) FROM EMPLOYEE t0, ...
objectAttributes can be specified also, even accross many to many mappings.

see
#addCount()

        addItem(itemName, attributeExpression.count());
    
public voidaddCount(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression, java.lang.Class resultType)
PUBLIC: Include the number of rows returned by the query in the result, where attributeExpression is not null. Aggregation functions can be used with a group by, or on the entire result set. Set the count to be returned as the specified resultType.

Example:

TopLink: reportQuery.addCount("Count", getExpressionBuilder().get("id"), Integer.class); SQL: SELECT COUNT (t0.EMP_ID) FROM EMPLOYEE t0, ...

Example: counting only distinct values of an attribute.

TopLink: reportQuery.addCount("Count", getExpressionBuilder().get("address").distinct()); SQL: SELECT COUNT (DISTINCT t0.ADDR_ID) FROM EMPLOYEE t0, ...
objectAttributes can be specified also, even accross many to many mappings.

see
#addCount()

        addItem(itemName, attributeExpression.count(), resultType);
    
public voidaddFunctionItem(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression, java.lang.String functionName)
ADVANCED: Add the function against the attribute expression to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. Example: reportQuery.addFunctionItem("average", expBuilder.get("salary"), "average");

        Expression functionExpression = attributeExpression;
        functionExpression = attributeExpression.getFunction(functionName);

        ReportItem item = new ReportItem(itemName, functionExpression);
        addItem(item);

    
public voidaddGrouping(java.lang.String attributeName)
PUBLIC: Add the attribute to the group by expressions. This will group the result set on that attribute and is normally used in conjunction with aggregation functions. Example: reportQuery.addGrouping("lastName")

        addGrouping(getExpressionBuilder().get(attributeName));
    
public voidaddGrouping(oracle.toplink.essentials.expressions.Expression expression)
PUBLIC: Add the attribute expression to the group by expressions. This will group the result set on that attribute and is normally used in conjunction with aggregation functions. Example: reportQuery.addGrouping(expBuilder.get("address").get("country"))

        getGroupByExpressions().addElement(expression);
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    
private voidaddItem(oracle.toplink.essentials.internal.queryframework.ReportItem item)
INTERNAL: Method used to abstract addToConstructorItem behavour from the public addItem methods

        if (addToConstructorItem && (getItems().size()>0) &&(((ReportItem)getItems().lastElement()).isContructorItem() )){
            ((ConstructorReportItem)getItems().lastElement()).addItem(item);
        }else{
            getItems().addElement(item);
        }
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    
public voidaddItem(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression)
ADVANCED: Add the expression value to be included in the result. EXAMPLE: reportQuery.addItem("name", expBuilder.get("firstName").toUpperCase());

        ReportItem item = new ReportItem(itemName, attributeExpression);
        addItem(item);
    
public voidaddItem(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression, java.util.List joinedExpressions)
ADVANCED: Add the expression value to be included in the result. EXAMPLE: reportQuery.addItem("name", expBuilder.get("firstName").toUpperCase());

        ReportItem item = new ReportItem(itemName, attributeExpression);
        item.getJoinedAttributeManager().setJoinedAttributeExpressions_(joinedExpressions);
        addItem(item);
    
protected voidaddItem(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression, java.lang.Class resultType)
INTERNAL: Add the expression value to be included in the result. EXAMPLE: reportQuery.addItem("name", expBuilder.get("firstName").toUpperCase()); The resultType can be specified to support EJBQL that adheres to the EJB 3.0 spec.

        ReportItem item = new ReportItem(itemName, attributeExpression);
        item.setResultType(resultType);
        addItem(item);
    
public voidaddMaximum(java.lang.String itemName)
PUBLIC: Add the maximum value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addMaximum("salary");

        addMaximum(itemName, getExpressionBuilder().get(itemName));
    
public voidaddMaximum(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression)
PUBLIC: Add the maximum value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addMaximum("managerSalary", expBuilder.get("manager").get("salary"));

        addItem(itemName, attributeExpression.maximum());
    
public voidaddMinimum(java.lang.String itemName)
PUBLIC: Add the minimum value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addMinimum("salary");

        addMinimum(itemName, getExpressionBuilder().get(itemName));
    
public voidaddMinimum(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression)
PUBLIC: Add the minimum value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addMinimum("managerSalary", expBuilder.get("manager").get("salary"));

        addItem(itemName, attributeExpression.minimum());
    
public voidaddStandardDeviation(java.lang.String itemName)
PUBLIC: Add the standard deviation value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addStandardDeviation("salary");

        addStandardDeviation(itemName, getExpressionBuilder().get(itemName));
    
public voidaddStandardDeviation(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression)
PUBLIC: Add the standard deviation value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addStandardDeviation("managerSalary", expBuilder.get("manager").get("salary"));

        addItem(itemName, attributeExpression.standardDeviation());
    
public voidaddSum(java.lang.String itemName)
PUBLIC: Add the sum value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addSum("salary");

        addSum(itemName, getExpressionBuilder().get(itemName));
    
public voidaddSum(java.lang.String itemName, java.lang.Class resultType)
PUBLIC: Add the sum value of the attribute to be included in the result and return it as the specified resultType. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addSum("salary", Float.class);

        addSum(itemName, getExpressionBuilder().get(itemName), resultType);
    
public voidaddSum(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression)
PUBLIC: Add the sum value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addSum("managerSalary", expBuilder.get("manager").get("salary"));

        addItem(itemName, attributeExpression.sum());
    
public voidaddSum(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression, java.lang.Class resultType)
PUBLIC: Add the sum value of the attribute to be included in the result and return it as the specified resultType. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addSum("managerSalary", expBuilder.get("manager").get("salary"), Float.class);

        addItem(itemName, attributeExpression.sum(), resultType);
    
public voidaddVariance(java.lang.String itemName)
PUBLIC: Add the variance value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addVariance("salary");

        addVariance(itemName, getExpressionBuilder().get(itemName));
    
public voidaddVariance(java.lang.String itemName, oracle.toplink.essentials.expressions.Expression attributeExpression)
PUBLIC: Add the variance value of the attribute to be included in the result. Aggregation functions can be used with a group by, or on the entire result set. EXAMPLE: reportQuery.addVariance("managerSalary", expBuilder.get("manager").get("salary"));

        addItem(itemName, attributeExpression.variance());
    
public oracle.toplink.essentials.queryframework.ConstructorReportItembeginAddingConstructorArguments(java.lang.Class constructorClass)
PUBLIC: Call a constructor for the given class with the results of this query.

param
constructorClass

        ConstructorReportItem citem = new ConstructorReportItem(constructorClass.getName());
        citem.setResultType(constructorClass);
        //add directly to avoid addToConstructorItem behaviour
        getItems().add(citem);
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
        this.addToConstructorItem=true;
        return citem;
    
public oracle.toplink.essentials.queryframework.ConstructorReportItembeginAddingConstructorArguments(java.lang.Class constructorClass, java.lang.Class[] constructorArgTypes)
PUBLIC: Call a constructor for the given class with the results of this query.

param
constructorClass
param
constructorArgTypes - sets the argument types to be passed to the constructor.

        ConstructorReportItem citem =beginAddingConstructorArguments(constructorClass);
        citem.setConstructorArgTypes(constructorArgTypes);
        return citem;
    
public java.lang.ObjectbuildObject(oracle.toplink.essentials.internal.sessions.AbstractRecord row, java.util.Vector toManyJoinData)
INTERNAL: Construct a result from a row. Either return a ReportQueryResult or just the attribute.

        ReportQueryResult reportQueryResult = new ReportQueryResult(this, row, toManyJoinData);
        //GF_ISSUE_395
        if (this.returnedKeys != null){
            if (this.returnedKeys.contains(reportQueryResult.getResultKey())){
                return RESULT_IGNORED; //distinguish between null values and thrown away duplicates
            } else {
                this.returnedKeys.add(reportQueryResult.getResultKey());
            }
        }
        //end GF_ISSUE_395
        if (this.shouldReturnSingleAttribute()) {
            return reportQueryResult.getResults().firstElement();
        } 
        if (this.shouldReturnWithoutReportQueryResult()){
            if (reportQueryResult.getResults().size() == 1){
                return reportQueryResult.getResults().firstElement();
            }
            return reportQueryResult.toArray();
        }
        return reportQueryResult;
    
public java.lang.ObjectbuildObjects(java.util.Vector rows)
INTERNAL: Construct a container of ReportQueryResult from the rows. If only one result or value was asked for only return that.

        if (shouldReturnSingleResult() || shouldReturnSingleValue()) {
            if (rows.isEmpty()) {
                return null;
            }
            ReportQueryResult result = (ReportQueryResult)buildObject((AbstractRecord)rows.firstElement(), rows);
            if (shouldReturnSingleValue()) {
                return result.elements().nextElement();
            }
            return result;
        }

        ContainerPolicy containerPolicy = getContainerPolicy();
        Object reportResults = containerPolicy.containerInstance(rows.size());
        // GF_ISSUE_395
        if (shouldDistinctBeUsed()){
            this.returnedKeys = new HashSet();
        }
        //end GF_ISSUE
        //If only the attribute is desired, then buildObject will only get the first attribute each time
        for (Enumeration rowsEnum = rows.elements(); rowsEnum.hasMoreElements();) {
            // GF_ISSUE_395
            Object result = buildObject((AbstractRecord)rowsEnum.nextElement(), rows);
            if (result != RESULT_IGNORED){
                containerPolicy.addInto(result, reportResults, getSession());
            }
            //end GF_ISSUE
        }
        return reportResults;
    
protected java.lang.ObjectcheckEarlyReturnImpl(oracle.toplink.essentials.internal.sessions.AbstractSession session, oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow)
INTERNAL: The cache check is done before the prepare as a hit will not require the work to be done.

        // Check for in-memory only query.
        if (shouldCheckCacheOnly()) {
            throw QueryException.cannotSetShouldCheckCacheOnlyOnReportQuery();
        } else {
            return null;
        }
    
public voidclearItems()
INTERNAL: Clear the ReportQueryItems

        items = new Vector();
        setIsPrepared(false);
    
public voidcopyReportItems(java.util.Dictionary alreadyDone)
INTERNAL: Required for a very special case of bug 2612185: ReportItems from parallelExpressions, on a ReportQuery which is a subQuery, which is being batch read. In a batch query the selection criteria is effectively cloned twice, meaning the ReportItems need to be cloned an extra time also to stay in sync. Each call to copiedVersionFrom() will take O(1) time as the expression was already cloned.

        items = (Vector)items.clone();
        for (int i = items.size() - 1; i >= 0; i--) {
            ReportItem item = (ReportItem)items.elementAt(i);
            Expression expression = item.getAttributeExpression();
            if ((expression != null) && (alreadyDone.get(expression.getBuilder()) != null)) {
                expression = expression.copiedVersionFrom(alreadyDone);
            }
            items.set(i, new ReportItem(item.getName(), expression));
        }
        if (groupByExpressions != null) {
            groupByExpressions = (Vector)groupByExpressions.clone();
            for (int i = groupByExpressions.size() - 1; i >= 0; i--) {
                Expression item = (Expression)groupByExpressions.elementAt(i);
                if (alreadyDone.get(item.getBuilder()) != null) {
                    groupByExpressions.set(i, item.copiedVersionFrom(alreadyDone));
                }
            }
        }
        if (orderByExpressions != null) {
            for (int i = orderByExpressions.size() - 1; i >= 0; i--) {
                Expression item = (Expression)orderByExpressions.elementAt(i);
                if (alreadyDone.get(item.getBuilder()) != null) {
                    orderByExpressions.set(i, item.copiedVersionFrom(alreadyDone));
                }
            }
        }
    
public voiddontRetrievePrimaryKeys()
PUBLIC: Set if the query results should contain the primary keys or each associated object. This make retrieving the real object easier. By default they are not retrieved.

        setShouldRetrievePrimaryKeys(false);
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    
public voiddontReturnSingleAttribute()
PUBLIC: Don't simplify the result by returning the single attribute. Wrap in a ReportQueryResult.

        if (shouldReturnSingleAttribute()) {
            returnChoice = 0;
        }
    
public voiddontReturnSingleResult()
PUBLIC: Simplifies the result by only returning the first result. This can be used if it known that only one row is returned by the report query.

        if (shouldReturnSingleResult()) {
            returnChoice = 0;
        }
    
public voiddontReturnSingleValue()
PUBLIC: Simplifies the result by only returning a single value. This can be used if it known that only one row is returned by the report query and only a single item is added to the report.

        if (shouldReturnSingleValue()) {
            returnChoice = 0;
        }
    
public voiddontReturnWithoutReportQueryResult()
PUBLIC: Simplifies the result by only returning a single value. This can be used if it known that only one row is returned by the report query and only a single item is added to the report.

        if (shouldReturnWithoutReportQueryResult()) {
            returnChoice = 0;
        }
    
public voidendAddingToConstructorItem()
PUBLIC: Used in conjunction with beginAddingConstructorArguments to signal that expressions should no longer be be added to the collection used in the constructor Get the rows and build the object from the rows.

exception
DatabaseException - an error has occurred on the database
return
Vector - collection of objects resulting from execution of query.

        this.addToConstructorItem=false;
    
public java.lang.ObjectexecuteDatabaseQuery()
INTERNAL: Execute the query. Get the rows and build the object from the rows.

exception
DatabaseException - an error has occurred on the database
return
Vector - collection of objects resulting from execution of query.

        // ensure a pessimistic locking query will go down the write connection
       if (isLockQuery() && getSession().isUnitOfWork()) {
            UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)getSession();
            // Note if a nested unit of work this will recursively start a
            // transaction early on the parent also.
            if (isLockQuery()) {
                if ((!unitOfWork.getCommitManager().isActive()) && (!unitOfWork.wasTransactionBegunPrematurely())) {
                    unitOfWork.beginTransaction();
                    unitOfWork.setWasTransactionBegunPrematurely(true);
                }
            }
        }
        
        if (getContainerPolicy().overridesRead()) {
            return getContainerPolicy().execute();
        }

        if (getQueryId() == 0) {
            setQueryId(getSession().getNextQueryId());
        }

        Vector rows = getQueryMechanism().selectAllReportQueryRows();
        // If using -m joins, must set all rows.
        return buildObjects(rows);
    
public java.util.VectorgetGroupByExpressions()
INTERNAL: Return the group bys.

        return groupByExpressions;
    
public oracle.toplink.essentials.expressions.ExpressiongetHavingExpression()
INTERNAL: Return the Having expression.

        return havingExpression;
    
public java.util.VectorgetItemExpressions()
INTERNAL: return a collection of expressions from the items. Ignore the null (place holders).

        Vector fieldExpressions = new Vector(getItems().size());

        // For bug 3115576 and an EXISTS subquery only need to return a single field.
        if (shouldRetrieveFirstPrimaryKey()) {
            if (!getDescriptor().getPrimaryKeyFields().isEmpty()) {
                fieldExpressions.addElement(getDescriptor().getPrimaryKeyFields().get(0));
            }
        }
        if (shouldRetrievePrimaryKeys()) {
            fieldExpressions.addAll(getDescriptor().getPrimaryKeyFields());
        }

        for (Enumeration itemsEnum = getItems().elements(); itemsEnum.hasMoreElements();) {
            ReportItem item = (ReportItem)itemsEnum.nextElement();
            Expression fieldExpression = item.getAttributeExpression();
            if (fieldExpression != null) {
                fieldExpressions.addElement(fieldExpression);
            }
        }
        return fieldExpressions;
    
public java.util.VectorgetItems()
INTERNAL:

return
ReportQueryItems defining the attributes to be read

        return items;
    
private oracle.toplink.essentials.mappings.DatabaseMappinggetMappingOfFirstPrimaryKey(oracle.toplink.essentials.descriptors.ClassDescriptor descriptor)

        if (descriptor != null) {
            for (Iterator i = descriptor.getMappings().iterator(); i.hasNext(); ) {
                DatabaseMapping m = (DatabaseMapping)i.next();
                if (m.isPrimaryKeyMapping()) {
                    return m;
                }
            }
        }
        return null;
    
public java.util.VectorgetNames()
INTERNAL: Lazily initialize and return the names of the items requested for use in each result object

        if (names == null) {
            names = new Vector();
            for (Enumeration e = getItems().elements(); e.hasMoreElements();) {
                names.addElement(((ReportItem)e.nextElement()).getName());
            }
        }
        return names;
    
public java.util.VectorgetQueryExpressions()
INTERNAL: return a collection of expressions if PK's are used.

        Vector fieldExpressions = new Vector(getItems().size());

        // For bug 3115576 and an EXISTS subquery only need to return a single field.
        if (shouldRetrieveFirstPrimaryKey()) {
            if (!getDescriptor().getPrimaryKeyFields().isEmpty()) {
                fieldExpressions.addElement(getDescriptor().getPrimaryKeyFields().get(0));
            }
        }
        if (shouldRetrievePrimaryKeys()) {
            fieldExpressions.addAll(getDescriptor().getPrimaryKeyFields());
        }

        return fieldExpressions;
    
public booleanisReportQuery()
PUBLIC: Return if this is a report query.

        return true;
    
protected voidprepare()
INTERNAL: Prepare the receiver for execution in a session. Initialize each item with its DTF mapping

        // Oct 19, 2000 JED
        // Added exception to be thrown if no attributes have been added to the query
        if (getItems().size() > 0) {
            try {
                for (Enumeration itemsEnum = getItems().elements(); itemsEnum.hasMoreElements();) {
                    ((ReportItem)itemsEnum.nextElement()).initialize(this);
                }
            } catch (QueryException exception) {
                exception.setQuery(this);
                throw exception;
            }
        } else {
            if ((!shouldRetrievePrimaryKeys()) && (!shouldRetrieveFirstPrimaryKey())) {
                throw QueryException.noAttributesForReportQuery(this);
            }
        }

        super.prepare();

    
protected voidprepareObjectAttributeCount(java.util.Dictionary clonedExpressions)
INTERNAL: Prepare a report query with a count defined on an object attribute. Added to fix bug 3268040, addCount(objectAttribute) not supported.

        prepareObjectAttributeCount(getItems(), clonedExpressions);
    
private voidprepareObjectAttributeCount(java.util.List items, java.util.Dictionary clonedExpressions)

        int numOfReportItems = items.size();
        //gf675: need to loop through all items to fix all count(..) instances
        for (int i =0;i<numOfReportItems; i++){
            ReportItem item = (ReportItem)items.get(i);
            if (item == null) {
                continue;
            } else if (item instanceof ConstructorReportItem) {
                // recursive call to process child ReportItems
                prepareObjectAttributeCount(((ConstructorReportItem)item).getReportItems(), clonedExpressions);
            } else if (item.getAttributeExpression() instanceof FunctionExpression) {
                FunctionExpression count = (FunctionExpression)item.getAttributeExpression();
                if (count.getOperator().getSelector() == ExpressionOperator.Count) {
                    Expression baseExp = count.getBaseExpression();
                    boolean distinctUsed = false;
                    if (baseExp.isFunctionExpression() && (((FunctionExpression)baseExp).getOperator().getSelector() == ExpressionOperator.Distinct)) {
                        distinctUsed = true;
                        baseExp = ((FunctionExpression)baseExp).getBaseExpression();
                    }
                    boolean outerJoin = false;
                    ClassDescriptor newDescriptor = null;
                    if (baseExp.isQueryKeyExpression()) {
                        // now need to find out if it is a direct to field or something else.
                        DatabaseMapping mapping = getLeafMappingFor(baseExp, getDescriptor());
                        if ((mapping != null) && !mapping.isDirectToFieldMapping()) {
                            newDescriptor = mapping.getReferenceDescriptor();
                            outerJoin = ((QueryKeyExpression)baseExp).shouldUseOuterJoin();
                        }
                    } else if (baseExp.isExpressionBuilder()) {
                        newDescriptor = getSession().getDescriptor(((ExpressionBuilder)baseExp).getQueryClass());
                    }
                    
                    if (newDescriptor != null) {
                        // At this point we are committed to rewriting the query.
                        if (newDescriptor.hasSimplePrimaryKey()) {
                            // case 1: simple PK =>
                            // treat COUNT(entity) as COUNT(entity.pk)
                            DatabaseMapping pk = getMappingOfFirstPrimaryKey(newDescriptor);
                            Expression countArg = baseExp.get(pk.getAttributeName());
                            if (distinctUsed) {
                                countArg = countArg.distinct();
                            }
                            count.setBaseExpression(countArg);
                            count.getChildren().setElementAt(countArg, 0);
                        } else if (!distinctUsed) {
                            // case 2: composite PK, but no DISTINCT =>
                            // pick a PK column for the COUNT aggregate
                            DatabaseMapping pk = getMappingOfFirstPrimaryKey(newDescriptor);
                            Expression countArg = baseExp.get(pk.getAttributeName());
                            while (pk.isAggregateObjectMapping()) {
                                newDescriptor = ((AggregateObjectMapping)pk).getReferenceDescriptor();
                                pk = getMappingOfFirstPrimaryKey(newDescriptor);
                                countArg = countArg.get(pk.getAttributeName());
                            }
                            count.setBaseExpression(countArg);
                            count.getChildren().setElementAt(countArg, 0);
                        } else if (!outerJoin) {
                            // case 3: composite PK and DISTINCT, but no
                            // outer join => previous solution using
                            // COUNT(*) and EXISTS subquery
                            
                            // If this is a subselect baseExp is yet uncloned,
                            // and will miss out if moved now from items into a selection criteria.
                            if (clonedExpressions != null) {
                                if (clonedExpressions.get(baseExp.getBuilder()) != null) {
                                    baseExp = (QueryKeyExpression)baseExp.copiedVersionFrom(clonedExpressions);
                                } else {
                                    baseExp = (QueryKeyExpression)baseExp.rebuildOn(getExpressionBuilder());
                                }
                            }
                            
                            // Now the reference class of the query needs to be reversed.
                            // See the bug description for an explanation.
                            ExpressionBuilder countBuilder = baseExp.getBuilder();
                            ExpressionBuilder outerBuilder = new ExpressionBuilder();
                            
                            ReportQuery subSelect = new ReportQuery(getReferenceClass(), countBuilder);
                            subSelect.setShouldRetrieveFirstPrimaryKey(true);
                            
                            // Make sure the outerBuilder does not appear on the left of the subselect.
                            // Putting a builder on the left is desirable to trigger an optimization.
                            if (getSelectionCriteria() != null) {
                                outerBuilder.setQueryClass(newDescriptor.getJavaClass());
                                subSelect.setSelectionCriteria(baseExp.equal(outerBuilder).and(getSelectionCriteria()));
                            } else {
                                subSelect.setSelectionCriteria(baseExp.equal(outerBuilder));
                            }
                            setSelectionCriteria(outerBuilder.exists(subSelect));
                            count.setBaseExpression(outerBuilder);
                            count.getChildren().setElementAt( outerBuilder, 0);
                            setReferenceClass(newDescriptor.getJavaClass());
                            changeDescriptor(getSession());
                        } else {
                            // case 4: composite PK, DISTINCT, outer join => 
                            // not supported, throw exception
                            throw QueryException.distinctCountOnOuterJoinedCompositePK(
                                newDescriptor, this);
                        }
                    }
                }
            }
        }
    
protected voidprepareSelectAllRows()
INTERNAL: Prepare the mechanism.

        prepareObjectAttributeCount(null);

        getQueryMechanism().prepareReportQuerySelectAllRows();
    
public synchronized voidprepareSubSelect(oracle.toplink.essentials.internal.sessions.AbstractSession session, oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow, java.util.Dictionary clonedExpressions)
INTERNAL: Prepare the receiver for being printed inside a subselect. This prepares the statement but not the call.

        if (isPrepared()) {
            return;
        }

        setIsPrepared(true);
        setSession(session);
        setTranslationRow(translationRow);

        checkDescriptor(getSession());

        if (descriptor.isAggregateDescriptor()) {
            // Not allowed
            throw QueryException.aggregateObjectCannotBeDeletedOrWritten(descriptor, this);
        }

        try {
            for (Enumeration itemsEnum = getItems().elements(); itemsEnum.hasMoreElements();) {
                ((ReportItem)itemsEnum.nextElement()).initialize(this);
            }
        } catch (QueryException exception) {
            exception.setQuery(this);
            throw exception;
        }

        prepareObjectAttributeCount(clonedExpressions);

        getQueryMechanism().prepareReportQuerySubSelect();

        setSession(null);
        setTranslationRow(null);
    
public voidretrievePrimaryKeys()
PUBLIC: Set if the query results should contain the primary keys or each associated object. This make retrieving the real object easier. By default they are not retrieved.

        setShouldRetrievePrimaryKeys(true);
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    
public voidreturnSingleAttribute()
PUBLIC: Simplify the result by returning a single attribute. Don't wrap in a ReportQueryResult.

        returnChoice = ShouldReturnSingleAttribute;
    
public voidreturnSingleResult()
PUBLIC: Simplifies the result by only returning the first result. This can be used if it known that only one row is returned by the report query.

        returnChoice = ShouldReturnSingleResult;
    
public voidreturnSingleValue()
PUBLIC: Simplifies the result by only returning a single value. This can be used if it known that only one row is returned by the report query and only a single item is added to the report.

        returnChoice = ShouldReturnSingleValue;
    
public voidreturnWithoutReportQueryResult()
PUBLIC: Simplifies the result by only returning a single value. This can be used if it known that only one row is returned by the report query and only a single item is added to the report.

        this.returnChoice = ShouldReturnWithoutReportQueryResult;
    
public voidsetHavingExpression(oracle.toplink.essentials.expressions.Expression expression)
PUBLIC: Add the expression to the query to be used in the HAVING clause. This epression will be used to filter the result sets after they are grouped. It must be used in conjunction with the GROUP BY clause. Example: reportQuery.setHavingExpression(expBuilder.get("address").get("country").equal("Canada"))

        havingExpression = expression;
        setIsPrepared(false);
    
public voidsetShouldRetrieveFirstPrimaryKey(boolean shouldRetrieveFirstPrimaryKey)
ADVANCED: Sets if the query results should contain the first primary key of each associated object. Usefull if this is an EXISTS subquery and you don't care what fields are returned so long as it is a single field. The default value is false. This should only be used with a subquery.

        this.shouldRetrievePrimaryKeys = (shouldRetrieveFirstPrimaryKey ? FIRST_PRIMARY_KEY : NO_PRIMARY_KEY);
    
public voidsetShouldRetrievePrimaryKeys(boolean shouldRetrievePrimaryKeys)
PUBLIC: Set if the query results should contain the primary keys or each associated object. This make retrieving the real object easier. By default they are not retrieved.

        this.shouldRetrievePrimaryKeys = (shouldRetrievePrimaryKeys ? FULL_PRIMARY_KEY : NO_PRIMARY_KEY);
    
public voidsetShouldReturnSingleAttribute(boolean newChoice)
PUBLIC: Simplifies the result by only returning the attribute (as opposed to wrapping in a ReportQueryResult). This can be used if it is known that only one attribute is returned by the report query.

        if (newChoice) {
            returnSingleAttribute();
        } else {
            dontReturnSingleAttribute();
        }
    
public voidsetShouldReturnSingleResult(boolean newChoice)
PUBLIC: Simplifies the result by only returning the first result. This can be used if it known that only one row is returned by the report query.

        if (newChoice) {
            returnSingleResult();
        } else {
            dontReturnSingleResult();
        }
    
public voidsetShouldReturnSingleValue(boolean newChoice)
PUBLIC: Simplifies the result by only returning a single value. This can be used if it known that only one row is returned by the report query and only a single item is added to the report.

        if (newChoice) {
            returnSingleValue();
        } else {
            dontReturnSingleValue();
        }
    
public voidsetShouldReturnWithoutReportQueryResult(boolean newChoice)
PUBLIC: Simplifies the result by returning a nested list instead of the ReportQueryResult. This is used by EJB 3.

        if (newChoice) {
            returnWithoutReportQueryResult();
        } else {
            dontReturnWithoutReportQueryResult();
        }
    
public booleanshouldRetrieveFirstPrimaryKey()
PUBLIC: Return if the query results should contain the first primary key of each associated object. Usefull if this is an EXISTS subquery and you don't care what fields are returned so long as it is a single field.

        return (shouldRetrievePrimaryKeys == FIRST_PRIMARY_KEY);
    
public booleanshouldRetrievePrimaryKeys()
PUBLIC: Return if the query results should contain the primary keys or each associated object. This make retrieving the real object easier.

        return (shouldRetrievePrimaryKeys == FULL_PRIMARY_KEY);
    
public booleanshouldReturnSingleAttribute()
PUBLIC: Answer if we are only returning the attribute (as opposed to wrapping in a ReportQueryResult). This can be used if it is known that only one attribute is returned by the report query.

        return returnChoice == ShouldReturnSingleAttribute;
    
public booleanshouldReturnSingleResult()
PUBLIC: Simplifies the result by only returning the first result. This can be used if it known that only one row is returned by the report query.

        return returnChoice == ShouldReturnSingleResult;
    
public booleanshouldReturnSingleValue()
PUBLIC: Simplifies the result by only returning a single value. This can be used if it known that only one row is returned by the report query and only a single item is added to the report.

        return returnChoice == ShouldReturnSingleValue;
    
public booleanshouldReturnWithoutReportQueryResult()
PUBLIC: Simplifies the result by returning a nested list instead of the ReportQueryResult. This is used by EJB 3.

        return returnChoice == ShouldReturnWithoutReportQueryResult;