Package org.datanucleus.store.query

Source Code of org.datanucleus.store.query.AbstractJDOQLQuery

/**********************************************************************
Copyright (c) 2007 Andy Jefferson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:
    ...
**********************************************************************/
package org.datanucleus.store.query;

import java.util.Iterator;
import java.util.Map;

import org.datanucleus.ObjectManager;
import org.datanucleus.exceptions.ClassNotResolvedException;
import org.datanucleus.query.JDOQLSingleStringParser;
import org.datanucleus.query.QueryUtils;
import org.datanucleus.query.compiler.JDOQLCompiler;
import org.datanucleus.query.compiler.JavaQueryCompiler;
import org.datanucleus.query.compiler.QueryCompilation;
import org.datanucleus.util.NucleusLogger;

/**
* Abstract representation of a JDOQL query.
* The query can be specified via method calls, or via a single-string form.
* @see Query
*/
public abstract class AbstractJDOQLQuery extends AbstractJavaQuery
{
    /**
     * Constructor.
     * @param om ObjectManager
     */
    public AbstractJDOQLQuery(ObjectManager om)
    {
        super(om);
    }

    /**
     * Constructs a new query instance having the same criteria as the given query.
     * @param om The ObjectManager
     * @param q The query from which to copy criteria.
     */
    public AbstractJDOQLQuery(ObjectManager om, AbstractJDOQLQuery q)
    {
        this(om);

        if (q == null)
        {
            candidateClass = null;
            candidateClassName = null;
            filter = null;
            imports = null;
            explicitVariables = null;
            explicitParameters = null;
            grouping = null;
            ordering = null;
            result = null;
            resultClass = null;
            resultClassName = null;
            resultDistinct = false;
            range = null;
            fromInclNo = 0;
            toExclNo = Long.MAX_VALUE;
        }
        else
        {
            candidateClass = q.candidateClass;
            candidateClassName = q.candidateClassName;
            filter = q.filter;
            imports = q.imports;
            explicitVariables = q.explicitVariables;
            explicitParameters = q.explicitParameters;
            grouping = q.grouping;
            ordering = q.ordering;
            result = q.result;
            resultClass = q.resultClass;
            resultClassName = q.resultClassName;
            resultDistinct = q.resultDistinct;
            range = q.range;
            fromInclNo = q.fromInclNo;
            toExclNo = q.toExclNo;
            ignoreCache = q.ignoreCache;
        }
    }

    /**
     * Constructor for a JDOQL query where the query is specified using the "Single-String" format.
     * @param om The persistence manager
     * @param query The query string
     */
    public AbstractJDOQLQuery(ObjectManager om, String query)
    {
        this(om);

        // Parse the single-string query for errors
        new JDOQLSingleStringParser(this, query).parse();

        if (candidateClassName != null)
        {
            try
            {
                // Set the candidateClass since the single-string parse only sets the candidateClassName
                // Note that the candidateClassName at this point could be unqualified
                candidateClass = getParsedImports().resolveClassDeclaration(candidateClassName,
                    om.getClassLoaderResolver(), null);
                candidateClassName = candidateClass.getName();
            }
            catch (ClassNotResolvedException e)
            {
                // TODO Localise this
                NucleusLogger.QUERY.warn("Candidate class for JDOQL single-string query (" + candidateClassName +
                    ") could not be resolved", e);
            }
        }
    }

    /**
     * Set the grouping specification for the result Collection.
     * @param grouping the grouping specification.
     */
    public void setGrouping(String grouping)
    {
        discardCompiled();
        assertIsModifiable();
       
        //discard previous values
        this.grouping = null;
        setHaving(null);

        if (grouping != null && grouping.length() > 0)
        {
            // The "grouping" string will be of the form "...., ...., ... HAVING ...."
            // so we parse it into the former part as a grouping clause, and the latter part as a having clause
            if (grouping.indexOf("HAVING") >= 0)
            {
                setHaving(grouping.substring(grouping.indexOf("HAVING") + 7));
                this.grouping = grouping.substring(0, grouping.indexOf("HAVING")-1);
            }
            else if (grouping.indexOf("having") >= 0)
            {
                setHaving(grouping.substring(grouping.indexOf("having") + 7));
                this.grouping = grouping.substring(0, grouping.indexOf("having")-1);
            }
            else
            {
                this.grouping = grouping.trim();
            }
        }
    }

    /**
     * Set the result for the results.
     * @param result Optional keyword "distinct" followed by comma-separated list of
     *     result expressions or a result class
     */
    public void setResult(String result)
    {
        discardCompiled();
        assertIsModifiable();
        if (result == null)
        {
            this.result = null;
            this.resultDistinct = false;
            return;
        }

        String str = result.trim();
        if (str.startsWith("distinct ") || str.startsWith("DISTINCT "))
        {
            this.resultDistinct = true;
            this.result = str.substring(8).trim();
        }
        else
        {
            this.resultDistinct = false;
            this.result = str;
        }
    }

    /**
     * Method to take the defined parameters for the query and form a single string.
     * This is used to print out the query for logging.
     * @return The single string
     */
    public String getSingleStringQuery()
    {
        if (singleString != null)
        {
            return singleString;
        }

        StringBuffer str = new StringBuffer("SELECT ");       
        if (unique)
        {
            str.append("UNIQUE ");
        }
        if (result != null)
        {
            if (resultDistinct)
            {
                str.append("DISTINCT ");
            }
            str.append(result + " ");
        }
        if (resultClassName != null)
        {
            str.append("INTO " + resultClassName + " ");
        }
        if (from != null)
        {
            // Subquery is of the form "<candidate-expression> alias"
            str.append("FROM " + from + " ");
        }
        else if (candidateClassName != null)
        {
            // Query is of the form "<candidate-class-name> [EXCLUDE-SUBCLASSES]"
            str.append("FROM " + candidateClassName + " ");
            if (!subclasses)
            {
                str.append("EXCLUDE SUBCLASSES ");
            }
        }
        if (filter != null)
        {
            str.append("WHERE " + filter + " ");
        }
        if (explicitVariables != null)
        {
            str.append("VARIABLES " + explicitVariables + " ");
        }
        if (explicitParameters != null)
        {
            str.append("PARAMETERS " + explicitParameters + " ");
        }
        if (imports != null)
        {
            str.append(imports + " ");
        }
        if (grouping != null)
        {
            str.append("GROUP BY " + grouping + " ");
        }
        if (having != null)
        {
            str.append("HAVING " + having + " ");
        }
        if (ordering != null)
        {
            str.append("ORDER BY " + ordering + " ");
        }

        if (range != null)
        {
            str.append("RANGE " + range);
        }
        else if (fromInclNo > 0 || toExclNo != Long.MAX_VALUE)
        {
            str.append("RANGE " + fromInclNo + "," + toExclNo);
        }

        singleString = str.toString().trim();
        return singleString;
    }

    /**
     * Method to compile the JDOQL query.
     * This implementation assumes that we are using the "generic" JDOQL compiler in
     * <i>org.datanucleus.query.compiler</i>. If not then override this method.
     * Will populate the "compilation" class variable.
     * @param forExecute Whether compiling for execution NOT USED HERE. TODO Remove this when possible
     * @param parameterValues Map of parameter values keyed by parameter name.
     */
    protected void compileInternal(boolean forExecute, Map parameterValues)
    {
        if (compilation != null)
        {
            return;
        }

        QueryManager queryMgr = om.getOMFContext().getQueryManager();
        boolean caching = getBooleanExtensionProperty("datanucleus.query.cached", true);
        if (caching)
        {
            QueryCompilation cachedCompilation = queryMgr.getQueryCompilationForQuery("JDOQL", toString());
            if (cachedCompilation != null)
            {
                if (NucleusLogger.QUERY.isDebugEnabled())
                {
                    NucleusLogger.QUERY.debug(LOCALISER.msg("021079", toString(), "JDOQL"));
                }
                compilation = cachedCompilation;
                checkParameterTypesAgainstCompilation(parameterValues);
                return;
            }
        }

        long startTime = 0;
        if (NucleusLogger.QUERY.isDebugEnabled())
        {
            startTime = System.currentTimeMillis();
            NucleusLogger.QUERY.debug(LOCALISER.msg("021044", "JDOQL", getSingleStringQuery()));
        }
        JavaQueryCompiler compiler = new JDOQLCompiler(om.getMetaDataManager(), om.getClassLoaderResolver(),
            null, candidateClass, candidateCollection,
            this.filter, getParsedImports(), this.ordering, this.result, this.grouping, this.having,
            explicitParameters, explicitVariables);
        compilation = compiler.compile(parameterValues, subqueries);
        if (QueryUtils.queryReturnsSingleRow(this))
        {
            compilation.setReturnsSingleRow();
        }
        if (NucleusLogger.QUERY.isDebugEnabled())
        {
            NucleusLogger.QUERY.debug(LOCALISER.msg("021045", "JDOQL",
                "" + (System.currentTimeMillis() - startTime)));
        }

        if (subqueries != null)
        {
            // Compile any subqueries
            Iterator iter = subqueries.entrySet().iterator();
            while (iter.hasNext())
            {
                Map.Entry entry = (Map.Entry)iter.next();
                SubqueryDefinition subqueryDefinition = (SubqueryDefinition)entry.getValue();
                Query subquery = subqueryDefinition.getQuery();
                if (NucleusLogger.QUERY.isDebugEnabled())
                {
                    startTime = System.currentTimeMillis();
                    NucleusLogger.QUERY.debug(LOCALISER.msg("021044", "JDOQL",
                        ((AbstractJDOQLQuery)subquery).getSingleStringQuery()));
                }
                compiler = new JDOQLCompiler(om.getMetaDataManager(), om.getClassLoaderResolver(),
                    null, subquery.candidateClass, null,
                    subquery.filter, getParsedImports(), subquery.ordering, subquery.result,
                    subquery.grouping, subquery.having, null, null);
                QueryCompilation subqueryCompilation = compiler.compile(parameterValues, null);
                if (QueryUtils.queryReturnsSingleRow(subquery))
                {
                    subqueryCompilation.setReturnsSingleRow();
                }
                compilation.addSubqueryCompilation((String)entry.getKey(), subqueryCompilation);
                if (NucleusLogger.QUERY.isDebugEnabled())
                {
                    NucleusLogger.QUERY.debug(LOCALISER.msg("021045", "JDOQL",
                        "" + (System.currentTimeMillis() - startTime)));
                }
            }
        }
        checkParameterTypesAgainstCompilation(parameterValues);

        if (caching)
        {
            // Cache for future reference
            queryMgr.addQueryCompilation("JDOQL", toString(), compilation);
        }
    }
}
TOP

Related Classes of org.datanucleus.store.query.AbstractJDOQLQuery

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.