Package org.apache.ojb.broker.accesslayer.sql

Source Code of org.apache.ojb.broker.accesslayer.sql.SqlSelectStatement

package org.apache.ojb.broker.accesslayer.sql;

/* Copyright 2002-2004 The Apache Software Foundation
*
* 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.
*/

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.query.Criteria;
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.query.ReportQuery;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.platforms.Platform;

/**
* Model a SELECT Statement
*
* @author <a href="mailto:jbraeuchi@hotmail.com">Jakob Braeuchi</a>
* @version $Id: SqlSelectStatement.java,v 1.22 2004/04/24 08:25:38 brj Exp $
*/
public class SqlSelectStatement extends SqlQueryStatement
{

    /**
     * Constructor for SqlSelectStatement.
     *
     * @param pf
     * @param cld
     * @param query
     * @param logger
     */
    public SqlSelectStatement(Platform pf, ClassDescriptor cld, Query query, Logger logger)
    {
        super(pf, cld, query, logger);
    }

    /**
     * Constructor for SqlSelectStatement.
     *
     * @param parent
     * @param pf
     * @param cld
     * @param query
     * @param logger
     */
    public SqlSelectStatement(SqlQueryStatement parent, Platform pf, ClassDescriptor cld, Query query, Logger logger)
    {
        super(parent, pf, cld, query, logger);
    }

    /**
     * Appends to the statement a comma separated list of column names.
     *
     * MBAIRD: if the object being queried on has multiple classes mapped to the table,
     * then we will get all the fields that are a unique set across all those classes so if we need to
     * we can materialize an extent
     *
     * DO NOT use this if order of columns is important. The row readers build reflectively and look up
     * column names to find values, so this is safe. In the case of update, you CANNOT use this as the
     * order of columns is important.
     *
     * @return list of column names for the set of all unique columns for multiple classes mapped to the
     * same table.
     */
    protected List appendListOfColumnsForSelect(ClassDescriptor cld, StringBuffer buf)
    {
        FieldDescriptor[] fieldDescriptors = cld.getRepository().getFieldDescriptorsForMultiMappedTable(cld);
        int fieldDescriptorLength = fieldDescriptors.length;
        ArrayList columnList = new ArrayList();
        int i = 0;

        if (fieldDescriptors != null)
        {
            FieldDescriptor field = null;
            for (int j = 0; j < fieldDescriptorLength; j++)
            {
                field = fieldDescriptors[j];
                if (i > 0)
                {
                    buf.append(",");
                }
                buf.append(getSearchTable().alias);
                buf.append(".");
                buf.append(field.getColumnName());
                columnList.add(field.getAttributeName());
                i++;
            }
        }
        return columnList;
    }

    /**
     * Appends to the statement a comma separated list of column names.
     *
     * @param columns defines the columns to be selected (for reports)
     * @return list of column names
     */
    protected List appendListOfColumns(String[] columns, StringBuffer buf)
    {
        ArrayList columnList = new ArrayList();

        for (int i = 0; i < columns.length; i++)
        {
            if (i > 0)
            {
                buf.append(",");
            }
            appendColName(columns[i], false, null, buf);
            columnList.add(columns[i]);
        }
        return columnList;
    }

    /**
     * Answer the SELECT-Sql for the Statement
     */
    public String getStatement()
    {
        StringBuffer stmt = new StringBuffer(1024);
        Query query = getQuery();
        boolean first = true;
        List orderByFields = null;
        int[] orderByColumnNumbers = null;
        String[] attributes = null;
        String[] joinAttributes = null;
        Iterator it = getJoinTreeToCriteria().entrySet().iterator();

        if (query instanceof ReportQuery)
        {
            attributes = ((ReportQuery) query).getAttributes();
            joinAttributes = ((ReportQuery) query).getJoinAttributes();
        }

        while (it.hasNext())
        {
            Map.Entry entry = (Map.Entry) it.next();
            Criteria whereCrit = (Criteria) entry.getValue();
            Criteria havingCrit = query.getHavingCriteria();
            List columnList;
            StringBuffer where = new StringBuffer();
            StringBuffer having = new StringBuffer();
            List groupByFields = null;

            // Set correct tree of joins for the current criteria
            setRoot((TableAlias) entry.getKey());

            if (whereCrit != null && whereCrit.isEmpty())
            {
                whereCrit = null;
            }

            if (havingCrit != null && havingCrit.isEmpty())
            {
                havingCrit = null;
            }

            if (first)
            {
                first = false;
            }
            else
            {
                stmt.append(" UNION ");
            }

            stmt.append("SELECT ");
            if (query.isDistinct())
            {
                stmt.append("DISTINCT ");
            }

            if (attributes == null || attributes.length == 0)
            {
                /**
                 * MBAIRD: use the appendListofColumnsForSelect, as it finds
                 * the union of select items for all object mapped to the same table. This
                 * will allow us to load objects with unique mapping fields that are mapped
                 * to the same table.
                 */
                columnList = appendListOfColumnsForSelect(getSearchClassDescriptor(), stmt);
            }
            else
            {
                columnList = appendListOfColumns(attributes, stmt);
            }

            // BRJ:
            // joinColumns are only used to force the building of a join;
            // they are not appended to the select-clause !
            // these columns are used in COUNT-ReportQueries and
            // are taken from the query the COUNT is based on
            if (joinAttributes != null && joinAttributes.length > 0)
            {
                for (int i = 0; i < joinAttributes.length; i++)
                {
                  // PAW: correct for pathClasses?
          //getAttributeInfo(joinAttributes[i], false, null);
          getAttributeInfo(joinAttributes[i], false, null, getQuery().getPathClasses());
                }
            }

            groupByFields = query.getGroupBy();
            if (groupByFields != null && !groupByFields.isEmpty())
            {
                ensureColumns(groupByFields, columnList, stmt);
            }

            orderByFields = query.getOrderBy();
            if (orderByFields != null && !orderByFields.isEmpty())
            {
                orderByColumnNumbers = ensureColumns(orderByFields, columnList, stmt);
            }

            /**
             * treeder: going to map superclass tables here,
             * not sure about the columns, just using all columns for now
             */
            ClassDescriptor cld = super.getBaseClassDescriptor();
            ClassDescriptor cldSuper = null;
            if (cld.getSuperClass() != null)
            {
                // then we have a super class so join tables
                cldSuper = cld.getRepository().getDescriptorFor(cld.getSuperClass());
                appendSuperClassColumns(cld, cldSuper, stmt);
            }

            stmt.append(" FROM ");

            appendTableWithJoins(getRoot(), where, stmt);
            if (cld.getSuperClass() != null)
            {
                appendSuperClassJoin(cld, cldSuper, stmt, where);
            }
           
            appendWhereClause(where, whereCrit, stmt);
            appendGroupByClause(groupByFields, stmt);
            appendHavingClause(having, havingCrit, stmt);
        }

        appendOrderByClause(orderByFields, orderByColumnNumbers, stmt);

        return stmt.toString();
    }

    private void appendSuperClassJoin(ClassDescriptor cld, ClassDescriptor cldSuper, StringBuffer stmt,
            StringBuffer where)
    {
        stmt.append(",").append(cldSuper.getFullTableName());
        if (where != null && where.length() > 0)
        {
            where.append(" AND ");
        }
        // get reference field in super class
        // TODO: do not use the superclassfield anymore, just assume that the id is the same in both tables - @see PBroker.storeToDb
        int superFieldRef = cld.getSuperClassFieldRef();
        FieldDescriptor refField = cld.getFieldDescriptorByIndex(superFieldRef);
        where.append(cldSuper.getFullTableName()).append(".").append(
                cldSuper.getAutoIncrementFields()[0].getColumnName());
        where.append(" = ");
        where.append(cld.getFullTableName()).append(".").append(refField.getColumnName());

    }

    private void appendSuperClassColumns(ClassDescriptor cldSub, ClassDescriptor cldSuper, StringBuffer buf)
    {
        FieldDescriptor[] fields = cldSuper.getFieldDescriptions();
        for (int i = 0; i < fields.length; i++)
        {
            FieldDescriptor field = fields[i];
            if (i > 0)
            {
                buf.append(",");
            }
            buf.append(cldSuper.getFullTableName());
            buf.append(".");
            buf.append(field.getColumnName());
            //columnList.add(field.getAttributeName());

        }

    }

}
TOP

Related Classes of org.apache.ojb.broker.accesslayer.sql.SqlSelectStatement

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.