db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b..@apache.org
Subject cvs commit: db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql TableAliasHandler.java SqlQueryStatement.java SqlSelectStatement.java SqlDeleteByQuery.java
Date Sun, 10 Oct 2004 09:24:57 GMT
brj         2004/10/10 02:24:57

  Modified:    src/java/org/apache/ojb/broker/accesslayer/sql
                        SqlQueryStatement.java SqlSelectStatement.java
                        SqlDeleteByQuery.java
  Added:       src/java/org/apache/ojb/broker/accesslayer/sql
                        TableAliasHandler.java
  Log:
  Refactoring of SqlQueryStatement. Alias- and Join-Handling moved to TableAliasHandler.
  
  Revision  Changes    Path
  1.86      +61 -913   db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java
  
  Index: SqlQueryStatement.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java,v
  retrieving revision 1.85
  retrieving revision 1.86
  diff -u -r1.85 -r1.86
  --- SqlQueryStatement.java	1 Oct 2004 20:12:33 -0000	1.85
  +++ SqlQueryStatement.java	10 Oct 2004 09:24:57 -0000	1.86
  @@ -15,26 +15,35 @@
    * limitations under the License.
    */
   
  -import java.util.ArrayList;
   import java.util.Collection;
  -import java.util.HashMap;
   import java.util.Iterator;
   import java.util.List;
   import java.util.Map;
  -import java.util.StringTokenizer;
   
   import org.apache.ojb.broker.PersistenceBrokerException;
  -import org.apache.ojb.broker.PersistenceBrokerSQLException;
   import org.apache.ojb.broker.accesslayer.JoinSyntaxTypes;
  +import org.apache.ojb.broker.accesslayer.sql.TableAliasHandler.Join;
  +import org.apache.ojb.broker.accesslayer.sql.TableAliasHandler.TableAlias;
   import org.apache.ojb.broker.metadata.ClassDescriptor;
  -import org.apache.ojb.broker.metadata.CollectionDescriptor;
  -import org.apache.ojb.broker.metadata.DescriptorRepository;
   import org.apache.ojb.broker.metadata.FieldDescriptor;
   import org.apache.ojb.broker.metadata.FieldHelper;
   import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
  -import org.apache.ojb.broker.metadata.fieldaccess.AnonymousPersistentFieldForInheritance;
   import org.apache.ojb.broker.platforms.Platform;
  -import org.apache.ojb.broker.query.*;
  +import org.apache.ojb.broker.query.BetweenCriteria;
  +import org.apache.ojb.broker.query.Criteria;
  +import org.apache.ojb.broker.query.ExistsCriteria;
  +import org.apache.ojb.broker.query.FieldCriteria;
  +import org.apache.ojb.broker.query.IdentityCriterion;
  +import org.apache.ojb.broker.query.InCriteria;
  +import org.apache.ojb.broker.query.LikeCriteria;
  +import org.apache.ojb.broker.query.MtoNQuery;
  +import org.apache.ojb.broker.query.NullCriteria;
  +import org.apache.ojb.broker.query.Query;
  +import org.apache.ojb.broker.query.QueryByCriteria;
  +import org.apache.ojb.broker.query.QueryBySQL;
  +import org.apache.ojb.broker.query.SelectionCriteria;
  +import org.apache.ojb.broker.query.SqlCriteria;
  +import org.apache.ojb.broker.query.UserAlias;
   import org.apache.ojb.broker.util.SqlHelper;
   import org.apache.ojb.broker.util.SqlHelper.PathInfo;
   import org.apache.ojb.broker.util.logging.Logger;
  @@ -48,30 +57,16 @@
    */
   public abstract class SqlQueryStatement implements SqlStatement, JoinSyntaxTypes
   {
  -    private static final String ALIAS_SEPARATOR = ".";
  -    
       private SqlQueryStatement m_parentStatement;
       /** the logger */
       private Logger m_logger;
  -    /** the target table of the query */
  -    private TableAlias m_root;
  -    /** the search table of the query */
  -    private TableAlias m_search;
       /** the query */
       private QueryByCriteria m_query;
  -    /** the mapping of paths to TableAliases */
  -    private HashMap m_pathToAlias = new HashMap();
  -    /** the mapping of ClassDescriptor to TableAliases */
  -    private HashMap m_cldToAlias = new HashMap();
  -    /** maps trees of joins to criteria */
  -    private HashMap m_joinTreeToCriteria = new HashMap();
   
       private Platform m_platform;
  -    private ClassDescriptor m_baseCld;
  -    private ClassDescriptor m_searchCld;
  -
  -    private int m_aliasCount = 0;
   
  +    private TableAliasHandler m_tableAliasHandler;
  +    
       /**
        * Constructor for SqlCriteriaStatement.
        *
  @@ -100,48 +95,25 @@
           m_parentStatement = parent;
           m_query = (QueryByCriteria) query;
           m_platform = pf;
  -        m_searchCld = cld;
   
  -        if ((m_query == null) || (m_query.getBaseClass() == m_query.getSearchClass()))
  +        if (parent != null)
           {
  -            m_baseCld = m_searchCld;
  +            m_tableAliasHandler = new TableAliasHandler(parent.m_tableAliasHandler, m_query, cld);
           }
           else
           {
  -            m_baseCld = cld.getRepository().getDescriptorFor(query.getBaseClass());
  -        }
  -
  -        m_root = createTableAlias(m_baseCld, null, "");
  -
  -        if (m_searchCld == m_baseCld)
  -        {
  -            m_search = m_root;
  -        }
  -        else
  -        {
  -			m_search = getTableAlias(m_query.getObjectProjectionAttribute(), false, null, null, m_query.getPathClasses());
  -        }
  -
  -        // Walk the super reference-descriptor
  -        buildSuperJoinTree(m_root, m_baseCld, "");
  -
  -        // In some cases it is necessary to split the query criteria
  -        // and then to generate UNION of several SELECTs
  -        // We build the joinTreeToCriteria mapping,
  -        if (query != null)
  -        {
  -            splitCriteria();
  +            m_tableAliasHandler = new TableAliasHandler(null, m_query, cld);            
           }
       }
   
       protected ClassDescriptor getBaseClassDescriptor()
       {
  -        return m_baseCld;
  +        return m_tableAliasHandler.getBaseClassDescriptor();
       }
   
       protected ClassDescriptor getSearchClassDescriptor()
       {
  -        return m_searchCld;
  +        return m_tableAliasHandler.getSearchClassDescriptor();
       }
   
   
  @@ -176,14 +148,14 @@
   		sp = colName.lastIndexOf(".");
   		if (sp == -1)
   		{
  -			tableAlias = getRoot();
  +			tableAlias = getRootAlias();
   		}
   		else
   		{
   			String pathName = colName.substring(0, sp);
   			String[] fieldNameRef = {colName.substring(sp + 1)};
   
  -			tableAlias = getTableAlias(pathName, useOuterJoins, aUserAlias, fieldNameRef, pathClasses);
  +			tableAlias = m_tableAliasHandler.getTableAlias(pathName, useOuterJoins, aUserAlias, fieldNameRef, pathClasses);
   			/**
   			 * if we have not found an alias by the pathName or
   			 * aliasName (if given), try again because pathName
  @@ -194,7 +166,7 @@
   			if ((tableAlias == null) && (colName.lastIndexOf(".") == -1))
   			{
   				// pathName might be an alias, so check this first
  -				tableAlias = getTableAlias(pathName, useOuterJoins, new UserAlias(pathName), null, pathClasses);
  +				tableAlias = m_tableAliasHandler.getTableAlias(pathName, useOuterJoins, new UserAlias(pathName), null, pathClasses);
   			}
   
   			if (tableAlias != null)
  @@ -381,7 +353,7 @@
       {
           FieldDescriptor fld = null;
   
  -        if (aTableAlias == getRoot())
  +        if (aTableAlias == getRootAlias())
           {
               // no path expression
               FieldDescriptor[] fk = anOrd.getForeignKeyFieldDescriptors(aTableAlias.cld);
  @@ -1025,7 +997,7 @@
        */
       private String getSubQuerySQL(Query subQuery)
       {
  -        ClassDescriptor cld = getRoot().cld.getRepository().getDescriptorFor(subQuery.getSearchClass());
  +        ClassDescriptor cld = getRootAlias().cld.getRepository().getDescriptorFor(subQuery.getSearchClass());
           String sql;
   
           if (subQuery instanceof QueryBySQL)
  @@ -1040,416 +1012,9 @@
           return sql;
       }
   
  -	/**
  -	 * Get TableAlias by the path from the target table of the query.
  -	 * @param aPath the path from the target table of the query to this TableAlias.
  -	 * @param useOuterJoins use outer join to join this table with the previous
  -	 * table in the path.
  -	 * @param aUserAlias if specified, overrides alias in crit
  -	 * @param fieldRef String[1] contains the field name.
  -	 * In the case of related table's primary key the "related.pk" attribute
  -	 * must not add new join, but use the value of foreign key
  -	 * @param pathClasses the hints 
  -	 */
  -	private TableAlias getTableAlias(String aPath, boolean useOuterJoins, UserAlias aUserAlias, String[] fieldRef, Map pathClasses)
  -	{
  -		TableAlias curr, prev, indirect;
  -		String attr, attrPath = null;
  -		ObjectReferenceDescriptor ord;
  -		CollectionDescriptor cod;
  -		ClassDescriptor cld = null;
  -		Object[] prevKeys = null;
  -		Object[] keys = null;
  -		ArrayList descriptors;
  -		boolean outer = useOuterJoins;
  -		int pathLength;
  -
  -		String pathAlias = aUserAlias == null ? null : aUserAlias.getAlias(aPath); 
  -		curr = getTableAliasForPath(aPath, pathAlias);
  -
  -		if (curr != null)
  -		{
  -			return curr;
  -		}
  -
  -		descriptors = getRoot().cld.getAttributeDescriptorsForPath(aPath, pathClasses);
  -		prev = getRoot();
  -
  -		if (descriptors == null || descriptors.size() == 0)
  -		{
  -			if (prev.hasJoins())
  -			{
  -				for (Iterator itr = prev.iterateJoins(); itr.hasNext();)
  -				{
  -					prev = ((Join) itr.next()).left;
  -					descriptors = prev.cld.getAttributeDescriptorsForPath(aPath, pathClasses);
  -					if (descriptors.size() > 0)
  -					{
  -						break;
  -					}
  -				}
  -			}
  -		}
  -
  -		pathLength = descriptors.size();
  -		for (int i = 0; i < pathLength; i++)
  -		{
  -			if (!(descriptors.get(i) instanceof ObjectReferenceDescriptor))
  -			{
  -				// only use Collection- and ObjectReferenceDescriptor
  -				continue;
  -			}
  -
  -			ord = (ObjectReferenceDescriptor) descriptors.get(i);
  -			attr = ord.getAttributeName();
  -			if (attrPath == null)
  -			{
  -				attrPath = attr;
  -			}
  -			else
  -			{
  -				attrPath = attrPath + "." + attr;
  -			}
  -
  -			// look for outer join hint
  -			outer = outer || getQuery().isPathOuterJoin(attr);
  -
  -			// look for 1:n or m:n
  -			if (ord instanceof CollectionDescriptor)
  -			{
  -				cod = (CollectionDescriptor) ord;
  -				cld = getItemClassDescriptor(cod, attrPath, pathClasses);
  -
  -				if (!cod.isMtoNRelation())
  -				{
  -					prevKeys = prev.cld.getPkFields();
  -					keys = cod.getForeignKeyFieldDescriptors(cld);
  -				}
  -				else
  -				{
  -					String mnAttrPath = attrPath + "*";
  -					String mnUserAlias = (aUserAlias == null ? null : aUserAlias + "*");
  -					indirect = getTableAliasForPath(mnAttrPath, mnUserAlias);
  -					if (indirect == null)
  -					{
  -						indirect = createTableAlias(cod.getIndirectionTable(), mnAttrPath, mnUserAlias);
  -
  -						// we need two Joins for m:n
  -						// 1.) prev class to indirectionTable
  -						prevKeys = prev.cld.getPkFields();
  -						keys = cod.getFksToThisClass();
  -						addJoin(prev, prevKeys, indirect, keys, outer, attr + "*");
  -					}
  -					// 2.) indirectionTable to the current Class
  -					prev = indirect;
  -					prevKeys = cod.getFksToItemClass();
  -					keys = cld.getPkFields();
  -				}
  -			}
  -			else
  -			{
  -				// must be n:1 or 1:1
  -				cld = getItemClassDescriptor(ord, attrPath, pathClasses);
  -
  -			    // BRJ : if ord is taken from 'super' we have to change prev accordingly
  -				if (!prev.cld.equals(ord.getClassDescriptor()))
  -				{
  -				    prev = getTableAliasForClassDescriptor(ord.getClassDescriptor());
  -				}	
  -
  -				prevKeys = ord.getForeignKeyFieldDescriptors(prev.cld);
  -				keys = cld.getPkFields();
  -
  -				// [olegnitz]
  -				// a special case: the last element of the path is
  -				// reference and the field is one of PK fields =>
  -				// use the correspondent foreign key field, don't add the join
  -				if ((fieldRef != null) && (i == (pathLength - 1)))
  -				{
  -					FieldDescriptor[] pk = cld.getPkFields();
  -
  -					for (int j = 0; j < pk.length; j++)
  -					{
  -						if (pk[j].getAttributeName().equals(fieldRef[0]))
  -						{
  -							fieldRef[0] = ((FieldDescriptor) prevKeys[j]).getAttributeName();
  -							return prev;
  -						}
  -					}
  -				}
  -			}
  -
  -			pathAlias = aUserAlias == null ? null : aUserAlias.getAlias(attrPath); 
  -			curr = getTableAliasForPath(attrPath, pathAlias);
  -
  -			if (curr == null)
  -			{
  -				List hintClasses = (List) pathClasses.get(aPath);
  -				curr = createTableAlias(cld, attrPath, pathAlias, hintClasses);
  -
  -				outer = outer || (curr.cld == prev.cld) || curr.hasExtents() || useOuterJoins;
  -				addJoin(prev, prevKeys, curr, keys, outer, attr);
  -
  -				buildSuperJoinTree(curr, cld, aPath);
  -			}
  -
  -			prev = curr;
  -		}
  -
  -		// PAW
  -		m_logger.debug("Result of getTableAlias(): " + curr);
  -		return curr;
  -	}
  -
  -    /**
  -     * add a join between two aliases
  -     * 
  -     * TODO BRJ : This needs refactoring, it looks kind of weird
  -     *
  -     * no extents
  -     * A1   -> A2
  -     *
  -     * extents on the right
  -     * A1   -> A2
  -     * A1   -> A2E0
  -     *
  -     * extents on the left : copy alias on right, extents point to copies
  -     * A1   -> A2
  -     * A1E0 -> A2C0
  -     *
  -     * extents on the left and right
  -     * A1   -> A2
  -     * A1   -> A2E0
  -     * A1E0 -> A2C0
  -     * A1E0 -> A2E0C0
  -     *
  -     * @param left
  -     * @param leftKeys
  -     * @param right
  -     * @param rightKeys
  -     * @param outer
  -     * @param name
  -     */
  -    private void addJoin(TableAlias left, Object[] leftKeys, TableAlias right, Object[] rightKeys, boolean outer,
  -            String name)
  -    {
  -        TableAlias extAlias, rightCopy;
  -
  -        left.addJoin(new Join(left, leftKeys, right, rightKeys, outer, name));
  -
  -        // build join between left and extents of right
  -        if (right.hasExtents())
  -        {
  -            for (int i = 0; i < right.extents.size(); i++)
  -            {
  -                extAlias = (TableAlias) right.extents.get(i);
  -                FieldDescriptor[] extKeys = getExtentFieldDescriptors(extAlias, (FieldDescriptor[]) rightKeys);
  -
  -                left.addJoin(new Join(left, leftKeys, extAlias, extKeys, true, name));
  -            }
  -        }
  -
  -        // we need to copy the alias on the right for each extent on the left
  -        if (left.hasExtents())
  -        {
  -            for (int i = 0; i < left.extents.size(); i++)
  -            {
  -                extAlias = (TableAlias) left.extents.get(i);
  -                FieldDescriptor[] extKeys = getExtentFieldDescriptors(extAlias, (FieldDescriptor[]) leftKeys);
  -                rightCopy = right.copy("C" + i);
  -
  -                // copies are treated like normal extents
  -                right.extents.add(rightCopy);
  -                right.extents.addAll(rightCopy.extents);
  -
  -                addJoin(extAlias, extKeys, rightCopy, rightKeys, true, name);
  -            }
  -        }
  -    }
  -
  -    /**
  -     * Get the FieldDescriptors of the extent based on the FieldDescriptors of the parent
  -     * @param extAlias
  -     * @param fds
  -     * @return
  -     */
  -    private FieldDescriptor[] getExtentFieldDescriptors(TableAlias extAlias, FieldDescriptor[] fds)
  -    {
  -        FieldDescriptor[] result = new FieldDescriptor[fds.length];
  -
  -        for (int i = 0; i < fds.length; i++)
  -        {
  -            result[i] = extAlias.cld.getFieldDescriptorByName(fds[i].getAttributeName());
  -        }
  -
  -        return result;
  -    }
  -
  -    private char getAliasChar()
  -    {
  -        char result = 'A';
  -
  -        if (m_parentStatement != null)
  -        {
  -            result = (char) (m_parentStatement.getAliasChar() + 1);
  -        }
  -
  -        return result;
  -    }
  -
  -    /**
  -     * Create a TableAlias for path or userAlias
  -     * @param aCld
  -     * @param aPath
  -     * @param aUserAlias
  -     * @param hints a List os Class objects to be used as hints for path expressions
  -     * @return TableAlias
  -     *
  -     */
  -    private TableAlias createTableAlias(ClassDescriptor aCld, String aPath, String aUserAlias, List hints)
  -    {
  -		if (aUserAlias == null)
  -		{
  -			return createTableAlias(aCld, hints, aPath);
  -		}
  -		else
  -		{
  -			return createTableAlias(aCld, hints, aUserAlias + ALIAS_SEPARATOR + aPath);
  -		}
  -    }
   
  -    /**
  -     * Create new TableAlias for path
  -     * @param cld the class descriptor for the TableAlias
  -     * @param path the path from the target table of the query to this TableAlias.
  -     * @param hints a List of Class objects to be used on path expressions
  -     */
  -    private TableAlias createTableAlias(ClassDescriptor cld, List hints, String path)
  -    {
  -        TableAlias alias;
  -        boolean lookForExtents = false;
  -
  -        if (!cld.getExtentClasses().isEmpty() && path.length() > 0)
  -        {
  -            lookForExtents = true;
  -        }
  -
  -        String aliasName = String.valueOf(getAliasChar()) + m_aliasCount++; // m_pathToAlias.size();
  -        alias = new TableAlias(cld, aliasName, lookForExtents, hints);
  -
  -        m_pathToAlias.put(path, alias);
  -        
  -        return alias;
  -    }
   
       /**
  -     * Create a TableAlias for path or userAlias
  -     * @param aTable
  -     * @param aPath
  -     * @param aUserAlias
  -     * @return TableAlias
  -     */
  -    private TableAlias createTableAlias(String aTable, String aPath, String aUserAlias)
  -    {
  -		if (aUserAlias == null)
  -		{
  -			return createTableAlias(aTable, aPath);
  -		}
  -		else
  -		{
  -			return createTableAlias(aTable, aUserAlias + ALIAS_SEPARATOR + aPath);
  -		}
  -    }
  -
  -    /**
  -     * Create new TableAlias for path
  -     * @param table the table name
  -     * @param path the path from the target table of the query to this TableAlias.
  -     */
  -    private TableAlias createTableAlias(String table, String path)
  -    {
  -        TableAlias alias;
  -
  -        if (table == null)
  -        {
  -            getLogger().warn("Creating TableAlias without table for path: " + path);
  -        }
  -
  -        String aliasName = String.valueOf(getAliasChar()) + m_aliasCount++; // + m_pathToAlias.size();
  -        alias = new TableAlias(table, aliasName);
  -        m_pathToAlias.put(path, alias);
  -        // PAW
  -		m_logger.debug("createTableAlias2: path: " + path + " tableAlias: " + alias);
  -
  -        return alias;
  -    }
  -
  -    /**
  -     * Answer the TableAlias for aPath
  -     * @param aPath
  -     * @return TableAlias, null if none
  -     */
  -    private TableAlias getTableAliasForPath(String aPath)
  -    {
  -        return (TableAlias) m_pathToAlias.get(aPath);
  -    }
  -
  -    /**
  -     * Answer the TableAlias for ClassDescriptor
  -     * @param aCld
  -     * @return
  -     */
  -    private TableAlias getTableAliasForClassDescriptor(ClassDescriptor aCld)
  -    {
  -        return (TableAlias) m_cldToAlias.get(aCld);
  -    }
  -    
  -    /**
  -     * Answer the TableAlias for aPath or aUserAlias
  -     * @param aPath
  -     * @param aUserAlias
  -     * @return TableAlias, null if none
  -     */
  -    private TableAlias getTableAliasForPath(String aPath, String aUserAlias)
  -    {
  -        if (aUserAlias == null)
  -        {
  -            return getTableAliasForPath(aPath);
  -        }
  -        else
  -        {
  -			return getTableAliasForPath(aUserAlias + ALIAS_SEPARATOR + aPath);
  -        }
  -    }
  -
  -	/**
  -	 * TODO: add super ClassDescriptor
  -	 * answer the ClassDescriptor for itemClass for an ObjectReferenceDescriptor
  -	 * check optional hint;
  -	 */
  -	private ClassDescriptor getItemClassDescriptor(ObjectReferenceDescriptor ord, String attr, Map pathClasses)
  -	{   
  -		List itemClasses = (List)pathClasses.get(attr);
  -
  -		if (itemClasses == null)
  -		{
  -			itemClasses = new ArrayList();
  -			itemClasses.add(ord.getItemClass());
  -		}
  -
  -		List classDescriptors = new ArrayList(itemClasses.size());
  -		DescriptorRepository repo = ord.getClassDescriptor().getRepository();
  -
  -		for (Iterator iter = itemClasses.iterator(); iter.hasNext();)
  -		{
  -			Class clazz = (Class) iter.next();
  -			classDescriptors.add(repo.getDescriptorFor(clazz));
  -		}
  -
  -		return (ClassDescriptor) classDescriptors.get(0);
  -	}
  -
  -	/**
        * Appends the ORDER BY clause for the Query.
        * <br>
        * If the orderByField is found in the list of selected fields it's index is added. 
  @@ -1534,7 +1099,7 @@
               stmtFromPos = buf.length(); // store position of join (by: Terry Dexter)
           }
   
  -        if (!(joinSyntax == SQL92_NOPAREN_JOIN_SYNTAX && alias != getRoot()))
  +        if (!(joinSyntax == SQL92_NOPAREN_JOIN_SYNTAX && alias != getRootAlias()))
           {
               buf.append(alias.getTableAndAlias());
   
  @@ -1586,7 +1151,7 @@
           {
               where.append(" AND ");
           }
  -        join.appendJoinEqualities(where);
  +        appendJoinEqualities(where,join);
       }
   
       /**
  @@ -1613,7 +1178,7 @@
               appendTableWithJoins(join.right, where, buf);
           }
           buf.append(" ON ");
  -        join.appendJoinEqualities(buf);
  +        appendJoinEqualities(buf,join);
       }
   
       /**
  @@ -1632,159 +1197,49 @@
   
           buf.append(join.right.getTableAndAlias());
           buf.append(" ON ");
  -        join.appendJoinEqualities(buf);
  +        appendJoinEqualities(buf, join);
   
           appendTableWithJoins(join.right, where, buf);
       }
   
       /**
  -     * Build Join Tree for SelectionCriteria
  -     * @param crit
  -     * @param useOuterJoin
  +     * Append the Join-keys
  +     * @param buf
  +     * @param join
        */
  -    private void buildJoinTree(SelectionCriteria crit, boolean useOuterJoin)
  +    private void appendJoinEqualities(StringBuffer buf, Join join)
       {
  -        // ignore SqlCriteria
  -        if (crit instanceof SqlCriteria)
  -        {
  -            return;
  -        }
  +        byte joinSyntax = getJoinSyntaxType();
   
  -        // handle IdentityCriteria as a collection of SelectionCriteria
  -        if (crit instanceof IdentityCriterion)
  +        for (int i = 0; i < join.leftKeys.length; i++)
           {
  -            IdentityCriterion idc = (IdentityCriterion) crit;
  -            Iterator idIter = idc.getCriteriaList().iterator();
  -            
  -            while (idIter.hasNext())
  +            if (i > 0)
               {
  -                buildJoinTree((SelectionCriteria) idIter.next(), useOuterJoin);
  +                buf.append(" AND ");
               }
  -            
  -            return;
  -        }
  -        
  -        // do not build join tree for subQuery attribute                  
  -        if (crit.getAttribute() != null && crit.getAttribute() instanceof String)
  -        {
  -			buildJoinTreeForAttribute((String) crit.getAttribute(), 
  -			        useOuterJoin, crit.getUserAlias(), crit.getPathClasses());
  -        }
  -        
  -        // handle the referenced Field
  -        if (crit instanceof FieldCriteria)
  -        {
  -            FieldCriteria cc = (FieldCriteria) crit;
  -			buildJoinTreeForAttribute((String) cc.getValue(), useOuterJoin, crit.getUserAlias(), crit.getPathClasses());
  -        }
  -            
  -    }    
  -        
  -    /**
  -     * Build the tree of joins for the given criteria
  -     */
  -    private void buildJoinTree(Criteria crit)
  -    {
  -        Iterator iter = crit.getIterator();
  +            buf.append(join.left.alias);
  +            buf.append(".");
  +            buf.append(join.leftKeys[i]);
   
  -        while (iter.hasNext())
  -        {
  -            Object c = iter.next();
  -            if (c instanceof Criteria)
  +            if (join.isOuter && joinSyntax == SYBASE_JOIN_SYNTAX)
               {
  -                buildJoinTree((Criteria) c);
  -            }
  -            else if (c instanceof SelectionCriteria)
  -            {
  -                boolean useOuterJoin = (crit.getType() == Criteria.OR);
  -                
  -                buildJoinTree((SelectionCriteria) c, useOuterJoin);
  +                buf.append("*=");
               }
               else
               {
  -                throw new PersistenceBrokerException("Don't know how to handle Criteria: " + c);
  +                buf.append("=");
               }
  -            
  -        }
  -    }
  -
  -	/**
  -	 * build the Join-Information for name
  -	 * functions and the last segment are removed
  -	 * ie: avg(accounts.amount) -> accounts
  -	 */
  -	private void buildJoinTreeForAttribute(String anAttribName, boolean useOuterJoin, UserAlias aUserAlias, Map pathClasses)
  -	{
  -		String pathName = SqlHelper.cleanPath(anAttribName);
  -		int sepPos = pathName.lastIndexOf(".");
   
  -		if (sepPos >= 0)
  -		{
  -			getTableAlias(pathName.substring(0, sepPos), useOuterJoin, aUserAlias,
  -						  new String[]{pathName.substring(sepPos + 1)}, pathClasses);
  -		}
  -	}
  +            buf.append(join.right.alias);
  +            buf.append(".");
  +            buf.append(join.rightKeys[i]);
   
  -	
  -    /**
  -     * build the Join-Information if a super reference exists
  -     *
  -     * @param left
  -     * @param cld
  -     * @param name
  -     */
  -    protected void buildSuperJoinTree(TableAlias left, ClassDescriptor cld, String name)
  -    {
  -        Iterator objRefs = cld.getObjectReferenceDescriptors().iterator();
  -        while (objRefs.hasNext())
  -        {
  -            ObjectReferenceDescriptor objRef = (ObjectReferenceDescriptor) objRefs.next();
  -            FieldDescriptor[] leftFields = objRef.getForeignKeyFieldDescriptors(cld);
  -
  -            ClassDescriptor refCld = cld.getRepository().getDescriptorFor(objRef.getItemClassName());
  -            if (objRef.getPersistentField() instanceof AnonymousPersistentFieldForInheritance)
  +            if (join.isOuter && joinSyntax == ORACLE_JOIN_SYNTAX)
               {
  -                TableAlias base_alias = getTableAliasForPath(name, null);
  -
  -                String aliasName = String.valueOf(getAliasChar()) + m_aliasCount++;
  -                TableAlias right = new TableAlias(refCld, aliasName, false, null);
  -
  -                Join join1to1 = new Join(left, leftFields, right, refCld.getPkFields(), false, "superClass");
  -                base_alias.addJoin(join1to1);
  -
  -                buildSuperJoinTree(right, refCld, name);
  +                buf.append("(+)");
               }
           }
       }
  -
  -    /**
  -     * First reduce the Criteria to the normal disjunctive form, then
  -     * calculate the necessary tree of joined tables for each item, then group
  -     * items with the same tree of joined tables.
  -     */
  -    protected void splitCriteria()
  -    {
  -        Criteria whereCrit = getQuery().getCriteria();
  -        Criteria havingCrit = getQuery().getHavingCriteria();
  -
  -        if (whereCrit == null || whereCrit.isEmpty())
  -        {
  -            getJoinTreeToCriteria().put(getRoot(), null);
  -        }
  -        else
  -        {
  -            // TODO: parameters list shold be modified when the form is reduced to DNF.
  -            getJoinTreeToCriteria().put(getRoot(), whereCrit);
  -            buildJoinTree(whereCrit);
  -        }
  -
  -        if (havingCrit != null && !havingCrit.isEmpty())
  -        {
  -            buildJoinTree(havingCrit);
  -        }
  -
  -    }
  - 
       
       /**
        * Gets the query.
  @@ -1799,18 +1254,18 @@
        * Gets the root.
        * @return Returns a TableAlias
        */
  -    protected TableAlias getRoot()
  +    protected TableAlias getRootAlias()
       {
  -        return m_root;
  +        return m_tableAliasHandler.getRootAlias();
       }
   
       /**
        * Sets the root.
        * @param root The root to set
        */
  -    protected void setRoot(TableAlias root)
  +    protected void setRootAlias(TableAlias root)
       {
  -        this.m_root = root;
  +        m_tableAliasHandler.setRootAlias(root);
       }
   
       /**
  @@ -1819,16 +1274,16 @@
        */
       protected TableAlias getSearchTable()
       {
  -        return m_search;
  +        return m_tableAliasHandler.getSearchTable();
       }
   
       /**
        * Gets the joinTreeToCriteria.
  -     * @return Returns a HashMap
  +     * @return Returns a Map
        */
  -    protected HashMap getJoinTreeToCriteria()
  +    protected Map getJoinTreeToCriteria()
       {
  -        return m_joinTreeToCriteria;
  +        return m_tableAliasHandler.getJoinTreeToCriteria();
       }
   
       /**
  @@ -1860,312 +1315,5 @@
       {
           TableAlias tableAlias;
           PathInfo pathInfo;
  -    }
  -
  -    /**
  -     * This class represents one table (possibly with alias) in the SQL query
  -     */
  -    final class TableAlias
  -    {
  -        Logger logger = LoggerFactory.getLogger(TableAlias.class);
  -        ClassDescriptor cld; // Is null for indirection table of M:N relation
  -        String table;
  -        final String alias;
  -        List extents = new ArrayList();
  -        List hints = new ArrayList();
  -        List joins;
  -
  -        TableAlias(String aTable, String anAlias)
  -        {
  -            this.cld = null;
  -            this.table = aTable;
  -            this.alias = anAlias;
  -        }
  -
  -        TableAlias(ClassDescriptor aCld, String anAlias)
  -        {
  -            this(aCld, anAlias, false, null);
  -        }
  -
  -        TableAlias(ClassDescriptor aCld, String anAlias, boolean lookForExtents, List hints)
  -        {
  -            this.cld = aCld;
  -            this.table = aCld.getFullTableName();
  -            this.alias = anAlias;
  -            boolean useHintsOnExtents = false;
  -
  -            // BRJ: store alias map of in enclosing class
  -			SqlQueryStatement.this.m_cldToAlias.put(aCld, this);
  -			
  -            //LEANDRO: use hints
  -            if (hints != null && hints.size() > 0)
  -            {
  -                useHintsOnExtents = true;
  -            }
  -
  -            logger.debug("TableAlias(): using hints ? " + useHintsOnExtents);
  -
  -            // BRJ : build alias for extents, only one per Table
  -            if (lookForExtents)
  -            {
  -                ClassDescriptor[] extCLDs = (ClassDescriptor[]) aCld.getRepository().getAllConcreteSubclassDescriptors(
  -                        aCld).toArray(new ClassDescriptor[0]);
  -
  -                ClassDescriptor extCd;
  -                Class extClass;
  -                String extTable;
  -                Map extMap = new HashMap(); // only one Alias per Table
  -                int firstNonAbstractExtentIndex = 0;
  -
  -                for (int i = 0; i < extCLDs.length; i++)
  -                {
  -                    extCd = extCLDs[i];
  -                    extClass = extCd.getClassOfObject();
  -                    if (useHintsOnExtents && (!hints.contains(extClass)))
  -                    {
  -                        //LEANDRO: don't include this class
  -                        logger.debug("Skipping class [" + extClass + "] from extents List");
  -                        firstNonAbstractExtentIndex++;
  -                        continue;
  -                    }
  -                    extTable = extCd.getFullTableName();
  -
  -                    // BRJ : Use the first non abstract extent
  -                    // if the main cld is abstract
  -                    //logger.debug("cld abstract["+aCld.isAbstract()+"] i["+i+"] index ["+firtsNonAbstractExtentIndex+"]");
  -                    if (aCld.isAbstract() && i == firstNonAbstractExtentIndex)
  -                    {
  -                        this.cld = extCd;
  -                        this.table = extTable;
  -                    }
  -                    else
  -                    {
  -                        // Add a new extent entry only if the table of the extent
  -                        // does not match the table of the 'base' class.
  -                        if (extMap.get(extTable) == null && !extTable.equals(table))
  -                        {
  -                            extMap.put(extTable, new TableAlias(extCd, anAlias + "E" + i, false, hints));
  -                        }
  -                    }
  -                }
  -                extents.addAll(extMap.values());
  -            }
  -
  -            if (cld == null)
  -            {
  -                throw new PersistenceBrokerSQLException("Table is NULL for alias: " + alias);
  -            }
  -        }
  -
  -        ClassDescriptor getClassDescriptor()
  -        {
  -            return cld;
  -        }
  -
  -        String getTableAndAlias()
  -        {
  -            return table + " " + alias;
  -        }
  -
  -        boolean hasExtents()
  -        {
  -            return (!extents.isEmpty());
  -        }
  -
  -        Iterator iterateExtents()
  -        {
  -            return extents.iterator();
  -        }
  -
  -        /**
  -         * Copy the Alias and all it's extents adding a Postfix
  -         * Joins are not copied
  -         * @param aPostfix
  -         * @return
  -         */
  -        TableAlias copy(String aPostfix)
  -        {
  -            TableAlias result, temp;
  -            Iterator iter = iterateExtents();
  -
  -            if (cld == null)
  -            {
  -                result = new TableAlias(table, alias + aPostfix);
  -            }
  -            else
  -            {
  -                result = new TableAlias(cld, alias + aPostfix);
  -            }
  -
  -            while (iter.hasNext())
  -            {
  -                temp = (TableAlias) iter.next();
  -                result.extents.add(temp.copy(aPostfix));
  -            }
  -
  -            return result;
  -        }
  -
  -        void addJoin(Join join)
  -        {
  -            if (joins == null)
  -            {
  -                joins = new ArrayList();
  -            }
  -            joins.add(join);
  -        }
  -
  -        Iterator iterateJoins()
  -        {
  -            return joins.iterator();
  -        }
  -
  -        boolean hasJoins()
  -        {
  -            return (joins != null);
  -        }
  -
  -        public String toString()
  -        {
  -            StringBuffer sb = new StringBuffer(1024);
  -            boolean first = true;
  -
  -            sb.append(getTableAndAlias());
  -            if (joins != null)
  -            {
  -                sb.append(" [");
  -                for (Iterator it = joins.iterator(); it.hasNext();)
  -                {
  -                    Join join = (Join) it.next();
  -
  -                    if (first)
  -                    {
  -                        first = false;
  -                    }
  -                    else
  -                    {
  -                        sb.append(", ");
  -                    }
  -                    sb.append("-(");
  -                    sb.append(join.name);
  -                    sb.append(")->");
  -                    sb.append(join.right);
  -                }
  -                sb.append("]");
  -            }
  -            return sb.toString();
  -        }
  -
  -        public boolean equals(Object obj)
  -        {
  -            TableAlias t = (TableAlias) obj;
  -
  -            return table.equals(t.table); // BRJ: check table only
  -        }
  -
  -        public int hashCode()
  -        {
  -            return table.hashCode();
  -        }
  -
  -    }
  -
  -    /**
  -     * This class represents join between two TableAliases
  -     */
  -    final class Join
  -    {
  -        final TableAlias left;
  -        final String[] leftKeys;
  -        final TableAlias right;
  -        final String[] rightKeys;
  -        final boolean isOuter;
  -        /** This is the name of the field corresponding to this join */
  -        final String name;
  -
  -        /**
  -         * leftKeys and rightKeys should be either FieldDescriptor[] or String[]
  -         */
  -        Join(TableAlias left, Object[] leftKeys, TableAlias right, Object[] rightKeys, boolean isOuter, String name)
  -        {
  -            this.left = left;
  -            this.leftKeys = getColumns(leftKeys);
  -            this.right = right;
  -            this.rightKeys = getColumns(rightKeys);
  -            this.isOuter = isOuter;
  -            this.name = name;
  -        }
  -
  -        private String[] getColumns(Object[] keys)
  -        {
  -            String[] columns = new String[keys.length];
  -
  -            if (keys instanceof FieldDescriptor[])
  -            {
  -                FieldDescriptor[] kd = (FieldDescriptor[]) keys;
  -                for (int i = 0; i < columns.length; i++)
  -                {
  -                    columns[i] = kd[i].getColumnName();
  -                }
  -            }
  -            else
  -            {
  -                for (int i = 0; i < columns.length; i++)
  -                {
  -                    columns[i] = keys[i].toString();
  -                }
  -            }
  -            return columns;
  -        }
  -
  -        void appendJoinEqualities(StringBuffer buf)
  -        {
  -            byte joinSyntax = getJoinSyntaxType();
  -
  -            for (int i = 0; i < leftKeys.length; i++)
  -            {
  -                if (i > 0)
  -                {
  -                    buf.append(" AND ");
  -                }
  -                buf.append(left.alias);
  -                buf.append(".");
  -                buf.append(leftKeys[i]);
  -
  -                if (isOuter && joinSyntax == SYBASE_JOIN_SYNTAX)
  -                {
  -                    buf.append("*=");
  -                }
  -                else
  -                {
  -                    buf.append("=");
  -                }
  -
  -                buf.append(right.alias);
  -                buf.append(".");
  -                buf.append(rightKeys[i]);
  -
  -                if (isOuter && joinSyntax == ORACLE_JOIN_SYNTAX)
  -                {
  -                    buf.append("(+)");
  -                }
  -            }
  -        }
  -
  -        public boolean equals(Object obj)
  -        {
  -            Join j = (Join) obj;
  -            return name.equals(j.name) && (isOuter == j.isOuter) && right.equals(j.right);
  -        }
  -
  -        public int hashCode()
  -        {
  -            return name.hashCode();
  -        }
  -
  -        public String toString()
  -        {
  -            return left.alias + " -> " + right.alias;
  -        }
       }
   }
  
  
  
  1.28      +6 -9      db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
  
  Index: SqlSelectStatement.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- SqlSelectStatement.java	1 Oct 2004 20:12:33 -0000	1.27
  +++ SqlSelectStatement.java	10 Oct 2004 09:24:57 -0000	1.28
  @@ -22,11 +22,11 @@
   
   import org.apache.ojb.broker.metadata.ClassDescriptor;
   import org.apache.ojb.broker.metadata.FieldDescriptor;
  +import org.apache.ojb.broker.platforms.Platform;
   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
  @@ -157,7 +157,7 @@
               List groupByFields = null;
   
               // Set correct tree of joins for the current criteria
  -            setRoot((TableAlias) entry.getKey());
  +            setRootAlias((TableAliasHandler.TableAlias) entry.getKey());
   
               if (whereCrit != null && whereCrit.isEmpty())
               {
  @@ -191,8 +191,7 @@
                    * 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.addAll(appendListOfColumnsForSelect(getSearchClassDescriptor(), stmt));
               }
               else
  @@ -223,7 +222,7 @@
                * treeder: going to map superclass tables here, 
                * not sure about the columns, just using all columns for now
                */
  -            ClassDescriptor cld = super.getBaseClassDescriptor();
  +            ClassDescriptor cld = getBaseClassDescriptor();
               ClassDescriptor cldSuper = null;
               if (cld.getSuperClass() != null)
               {
  @@ -233,8 +232,8 @@
               }
   
               stmt.append(" FROM ");
  +            appendTableWithJoins(getRootAlias(), where, stmt);
   
  -            appendTableWithJoins(getRoot(), where, stmt);
               if (cld.getSuperClass() != null)
               {
                   appendSuperClassJoin(cld, cldSuper, stmt, where);
  @@ -282,8 +281,6 @@
               buf.append(cldSuper.getFullTableName());
               buf.append(".");
               buf.append(field.getColumnName());
  -            //columnList.add(field.getAttributeName());
  -
           }
   
       }
  
  
  
  1.16      +2 -2      db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlDeleteByQuery.java
  
  Index: SqlDeleteByQuery.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlDeleteByQuery.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- SqlDeleteByQuery.java	4 Apr 2004 23:53:32 -0000	1.15
  +++ SqlDeleteByQuery.java	10 Oct 2004 09:24:57 -0000	1.16
  @@ -61,7 +61,7 @@
   	/* (non-Javadoc)
   	 * @see org.apache.ojb.broker.accesslayer.sql.SqlQueryStatement#getColName(org.apache.ojb.broker.accesslayer.sql.SqlQueryStatement.TableAlias, org.apache.ojb.broker.util.SqlHelper.PathInfo, boolean)
   	 */
  -	protected String getColName(TableAlias aTableAlias, PathInfo aPathInfo, boolean translate)
  +	protected String getColName(TableAliasHandler.TableAlias aTableAlias, PathInfo aPathInfo, boolean translate)
   	{
           FieldDescriptor fld = null;
           String result;
  
  
  
  1.1                  db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/TableAliasHandler.java
  
  Index: TableAliasHandler.java
  ===================================================================
  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.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import org.apache.ojb.broker.PersistenceBrokerException;
  import org.apache.ojb.broker.PersistenceBrokerSQLException;
  import org.apache.ojb.broker.metadata.ClassDescriptor;
  import org.apache.ojb.broker.metadata.CollectionDescriptor;
  import org.apache.ojb.broker.metadata.DescriptorRepository;
  import org.apache.ojb.broker.metadata.FieldDescriptor;
  import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
  import org.apache.ojb.broker.metadata.fieldaccess.AnonymousPersistentFieldForInheritance;
  import org.apache.ojb.broker.query.Criteria;
  import org.apache.ojb.broker.query.FieldCriteria;
  import org.apache.ojb.broker.query.IdentityCriterion;
  import org.apache.ojb.broker.query.QueryByCriteria;
  import org.apache.ojb.broker.query.SelectionCriteria;
  import org.apache.ojb.broker.query.SqlCriteria;
  import org.apache.ojb.broker.query.UserAlias;
  import org.apache.ojb.broker.util.SqlHelper;
  import org.apache.ojb.broker.util.SqlHelper.PathInfo;
  import org.apache.ojb.broker.util.logging.Logger;
  import org.apache.ojb.broker.util.logging.LoggerFactory;
  
  /**
   * Helper Class for TableAlias and Join Handling
   *
   * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
   * @version $Id: TableAliasHandler.java,v 1.1 2004/10/10 09:24:57 brj Exp $
   */
  class TableAliasHandler
  {
      private static final String ALIAS_SEPARATOR = ".";
      
      /** the query */
      private QueryByCriteria m_query;
      /** the target table of the query */
      private TableAlias m_rootAlias;
      /** the search table of the query */
      private TableAlias m_searchAlias;
      /** the mapping of paths to TableAliases */
      private Map m_pathToAlias = new HashMap();
      /** the mapping of ClassDescriptor to TableAliases */
      private Map m_cldToAlias = new HashMap();
      /** maps trees of joins to criteria */
      private Map m_joinTreeToCriteria = new HashMap();
      /** the logger */
      private Logger m_logger;
      private TableAliasHandler m_parentHandler;
      private ClassDescriptor m_baseCld;
      private ClassDescriptor m_searchCld;
  
      private int m_aliasCount = 0;
  
      
      TableAliasHandler(TableAliasHandler parent, QueryByCriteria aQuery, ClassDescriptor searchCld)
      {      
          m_logger = LoggerFactory.getLogger(TableAliasHandler.class);
          m_query = aQuery;       
          m_parentHandler = parent;
          m_searchCld = searchCld;
  
          if ((m_query == null) || (m_query.getBaseClass() == m_query.getSearchClass()))
          {
              m_baseCld = searchCld;
          }
          else
          {
              m_baseCld = searchCld.getRepository().getDescriptorFor(m_query.getBaseClass());
          }
  
          m_rootAlias = createTableAlias(m_baseCld, null, "");
  
          if (searchCld == m_baseCld)
          {
              m_searchAlias = m_rootAlias;
          }
          else
          {
  			m_searchAlias = getTableAlias(m_query.getObjectProjectionAttribute(), false, null, null, m_query.getPathClasses());
          }
  
          // Walk the super reference-descriptor
          buildSuperJoinTree(m_rootAlias, m_baseCld, "");
  
          // In some cases it is necessary to split the query criteria
          // and then to generate UNION of several SELECTs
          // We build the joinTreeToCriteria mapping,
          if (m_query != null)
          {
              splitCriteria();
          }
          
      }
      
      /**
       * Gets the query.
       * @return Returns a Query
       */
      private QueryByCriteria getQuery()
      {
          return m_query;
      }
  
      /**
       * Gets the root.
       * @return Returns a TableAlias
       */
      TableAlias getRootAlias()
      {
          return m_rootAlias;
      }
  
      /**
       * Sets the root.
       * @param root The root to set
       */
      void setRootAlias(TableAlias root)
      {
          this.m_rootAlias = root;
      }
  
      ClassDescriptor getBaseClassDescriptor()
      {
          return m_baseCld;
      }
  
      ClassDescriptor getSearchClassDescriptor()
      {
          return m_searchCld;
      }
      
      /**
       * Gets the search table of this query.
       * @return Returns a TableAlias
       */
      TableAlias getSearchTable()
      {
          return m_searchAlias;
      }
      
      /**
       * Gets the joinTreeToCriteria.
       * @return Returns a Map
       */
      Map getJoinTreeToCriteria()
      {
          return m_joinTreeToCriteria;
      }
      
      /**
       * First reduce the Criteria to the normal disjunctive form, then
       * calculate the necessary tree of joined tables for each item, then group
       * items with the same tree of joined tables.
       */
      private void splitCriteria()
      {
          Criteria whereCrit = getQuery().getCriteria();
          Criteria havingCrit = getQuery().getHavingCriteria();
  
          if (whereCrit == null || whereCrit.isEmpty())
          {
              getJoinTreeToCriteria().put(getRootAlias(), null);
          }
          else
          {
              // TODO: parameters list shold be modified when the form is reduced to DNF.
              getJoinTreeToCriteria().put(getRootAlias(), whereCrit);
              buildJoinTree(whereCrit);
          }
  
          if (havingCrit != null && !havingCrit.isEmpty())
          {
              buildJoinTree(havingCrit);
          }
  
      }
   
  
  	/**
  	 * TODO: add super ClassDescriptor
  	 * answer the ClassDescriptor for itemClass for an ObjectReferenceDescriptor
  	 * check optional hint;
  	 */
  	private ClassDescriptor getItemClassDescriptor(ObjectReferenceDescriptor ord, String attr, Map pathClasses)
  	{   
  		List itemClasses = (List)pathClasses.get(attr);
  
  		if (itemClasses == null)
  		{
  			itemClasses = new ArrayList();
  			itemClasses.add(ord.getItemClass());
  		}
  
  		List classDescriptors = new ArrayList(itemClasses.size());
  		DescriptorRepository repo = ord.getClassDescriptor().getRepository();
  
  		for (Iterator iter = itemClasses.iterator(); iter.hasNext();)
  		{
  			Class clazz = (Class) iter.next();
  			classDescriptors.add(repo.getDescriptorFor(clazz));
  		}
  
  		return (ClassDescriptor) classDescriptors.get(0);
  	}
  
      /**
       * Answer the TableAlias for aPath
       * @param aPath
       * @return TableAlias, null if none
       */
      private TableAlias getTableAliasForPath(String aPath)
      {
          return (TableAlias) m_pathToAlias.get(aPath);
      }
  
      /**
       * Answer the TableAlias for ClassDescriptor
       * @param aCld
       * @return
       */
      private TableAlias getTableAliasForClassDescriptor(ClassDescriptor aCld)
      {
          return (TableAlias) m_cldToAlias.get(aCld);
      }
      
      /**
       * Answer the TableAlias for aPath or aUserAlias
       * @param aPath
       * @param aUserAlias
       * @return TableAlias, null if none
       */
      private TableAlias getTableAliasForPath(String aPath, String aUserAlias)
      {
          if (aUserAlias == null)
          {
              return getTableAliasForPath(aPath);
          }
          else
          {
  			return getTableAliasForPath(aUserAlias + ALIAS_SEPARATOR + aPath);
          }
      }
      
  	/**
  	 * Get TableAlias by the path from the target table of the query.
  	 * @param aPath the path from the target table of the query to this TableAlias.
  	 * @param useOuterJoins use outer join to join this table with the previous
  	 * table in the path.
  	 * @param aUserAlias if specified, overrides alias in crit
  	 * @param fieldRef String[1] contains the field name.
  	 * In the case of related table's primary key the "related.pk" attribute
  	 * must not add new join, but use the value of foreign key
  	 * @param pathClasses the hints 
  	 */
  	TableAlias getTableAlias(String aPath, boolean useOuterJoins, UserAlias aUserAlias, String[] fieldRef, Map pathClasses)
  	{
  		TableAlias curr, prev, indirect;
  		String attr, attrPath = null;
  		ObjectReferenceDescriptor ord;
  		CollectionDescriptor cod;
  		ClassDescriptor cld = null;
  		Object[] prevKeys = null;
  		Object[] keys = null;
  		ArrayList descriptors;
  		boolean outer = useOuterJoins;
  		int pathLength;
  
  		String pathAlias = aUserAlias == null ? null : aUserAlias.getAlias(aPath); 
  		curr = getTableAliasForPath(aPath, pathAlias);
  
  		if (curr != null)
  		{
  			return curr;
  		}
  
  		descriptors = getRootAlias().cld.getAttributeDescriptorsForPath(aPath, pathClasses);
  		prev = getRootAlias();
  
  		if (descriptors == null || descriptors.size() == 0)
  		{
  			if (prev.hasJoins())
  			{
  				for (Iterator itr = prev.iterateJoins(); itr.hasNext();)
  				{
  					prev = ((Join) itr.next()).left;
  					descriptors = prev.cld.getAttributeDescriptorsForPath(aPath, pathClasses);
  					if (descriptors.size() > 0)
  					{
  						break;
  					}
  				}
  			}
  		}
  
  		pathLength = descriptors.size();
  		for (int i = 0; i < pathLength; i++)
  		{
  			if (!(descriptors.get(i) instanceof ObjectReferenceDescriptor))
  			{
  				// only use Collection- and ObjectReferenceDescriptor
  				continue;
  			}
  
  			ord = (ObjectReferenceDescriptor) descriptors.get(i);
  			attr = ord.getAttributeName();
  			if (attrPath == null)
  			{
  				attrPath = attr;
  			}
  			else
  			{
  				attrPath = attrPath + "." + attr;
  			}
  
  			// look for outer join hint
  			outer = outer || getQuery().isPathOuterJoin(attr);
  
  			// look for 1:n or m:n
  			if (ord instanceof CollectionDescriptor)
  			{
  				cod = (CollectionDescriptor) ord;
  				cld = getItemClassDescriptor(cod, attrPath, pathClasses);
  
  				if (!cod.isMtoNRelation())
  				{
  					prevKeys = prev.cld.getPkFields();
  					keys = cod.getForeignKeyFieldDescriptors(cld);
  				}
  				else
  				{
  					String mnAttrPath = attrPath + "*";
  					String mnUserAlias = (aUserAlias == null ? null : aUserAlias + "*");
  					indirect = getTableAliasForPath(mnAttrPath, mnUserAlias);
  					if (indirect == null)
  					{
  						indirect = createTableAlias(cod.getIndirectionTable(), mnAttrPath, mnUserAlias);
  
  						// we need two Joins for m:n
  						// 1.) prev class to indirectionTable
  						prevKeys = prev.cld.getPkFields();
  						keys = cod.getFksToThisClass();
  						addJoin(prev, prevKeys, indirect, keys, outer, attr + "*");
  					}
  					// 2.) indirectionTable to the current Class
  					prev = indirect;
  					prevKeys = cod.getFksToItemClass();
  					keys = cld.getPkFields();
  				}
  			}
  			else
  			{
  				// must be n:1 or 1:1
  				cld = getItemClassDescriptor(ord, attrPath, pathClasses);
  
  			    // BRJ : if ord is taken from 'super' we have to change prev accordingly
  				if (!prev.cld.equals(ord.getClassDescriptor()))
  				{
  				    prev = getTableAliasForClassDescriptor(ord.getClassDescriptor());
  				}	
  
  				prevKeys = ord.getForeignKeyFieldDescriptors(prev.cld);
  				keys = cld.getPkFields();
  
  				// [olegnitz]
  				// a special case: the last element of the path is
  				// reference and the field is one of PK fields =>
  				// use the correspondent foreign key field, don't add the join
  				if ((fieldRef != null) && (i == (pathLength - 1)))
  				{
  					FieldDescriptor[] pk = cld.getPkFields();
  
  					for (int j = 0; j < pk.length; j++)
  					{
  						if (pk[j].getAttributeName().equals(fieldRef[0]))
  						{
  							fieldRef[0] = ((FieldDescriptor) prevKeys[j]).getAttributeName();
  							return prev;
  						}
  					}
  				}
  			}
  
  			pathAlias = aUserAlias == null ? null : aUserAlias.getAlias(attrPath); 
  			curr = getTableAliasForPath(attrPath, pathAlias);
  
  			if (curr == null)
  			{
  				List hintClasses = (List) pathClasses.get(aPath);
  				curr = createTableAlias(cld, attrPath, pathAlias, hintClasses);
  
  				outer = outer || (curr.cld == prev.cld) || curr.hasExtents() || useOuterJoins;
  				addJoin(prev, prevKeys, curr, keys, outer, attr);
  
  				buildSuperJoinTree(curr, cld, aPath);
  			}
  
  			prev = curr;
  		}
  
  		m_logger.debug("Result of getTableAlias(): " + curr);
  
  		return curr;
  	}
  
      /**
       * Get the FieldDescriptors of the extent based on the FieldDescriptors of the parent
       * @param extAlias
       * @param fds
       * @return
       */
      private FieldDescriptor[] getExtentFieldDescriptors(TableAlias extAlias, FieldDescriptor[] fds)
      {
          FieldDescriptor[] result = new FieldDescriptor[fds.length];
  
          for (int i = 0; i < fds.length; i++)
          {
              result[i] = extAlias.cld.getFieldDescriptorByName(fds[i].getAttributeName());
          }
  
          return result;
      }
  
      private char getAliasChar()
      {
          char result = 'A';
  
          if (m_parentHandler != null)
          {
              result = (char) (m_parentHandler.getAliasChar() + 1);
          }
  
          return result;
      }
  	
      /**
       * add a join between two aliases
       * 
       * TODO BRJ : This needs refactoring, it looks kind of weird
       *
       * no extents
       * A1   -> A2
       *
       * extents on the right
       * A1   -> A2
       * A1   -> A2E0
       *
       * extents on the left : copy alias on right, extents point to copies
       * A1   -> A2
       * A1E0 -> A2C0
       *
       * extents on the left and right
       * A1   -> A2
       * A1   -> A2E0
       * A1E0 -> A2C0
       * A1E0 -> A2E0C0
       *
       * @param left
       * @param leftKeys
       * @param right
       * @param rightKeys
       * @param outer
       * @param name
       */
      private void addJoin(TableAlias left, Object[] leftKeys, TableAlias right, Object[] rightKeys, boolean outer,
              String name)
      {
          TableAlias extAlias, rightCopy;
  
          left.addJoin(new Join(left, leftKeys, right, rightKeys, outer, name));
  
          // build join between left and extents of right
          if (right.hasExtents())
          {
              for (int i = 0; i < right.extents.size(); i++)
              {
                  extAlias = (TableAlias) right.extents.get(i);
                  FieldDescriptor[] extKeys = getExtentFieldDescriptors(extAlias, (FieldDescriptor[]) rightKeys);
  
                  left.addJoin(new Join(left, leftKeys, extAlias, extKeys, true, name));
              }
          }
  
          // we need to copy the alias on the right for each extent on the left
          if (left.hasExtents())
          {
              for (int i = 0; i < left.extents.size(); i++)
              {
                  extAlias = (TableAlias) left.extents.get(i);
                  FieldDescriptor[] extKeys = getExtentFieldDescriptors(extAlias, (FieldDescriptor[]) leftKeys);
                  rightCopy = right.copy("C" + i);
  
                  // copies are treated like normal extents
                  right.extents.add(rightCopy);
                  right.extents.addAll(rightCopy.extents);
  
                  addJoin(extAlias, extKeys, rightCopy, rightKeys, true, name);
              }
          }
      }
  	
  	
      /**
       * Create a TableAlias for path or userAlias
       * @param aCld
       * @param aPath
       * @param aUserAlias
       * @param hints a List os Class objects to be used as hints for path expressions
       * @return TableAlias
       *
       */
      private TableAlias createTableAlias(ClassDescriptor aCld, String aPath, String aUserAlias, List hints)
      {
  		if (aUserAlias == null)
  		{
  			return createTableAlias(aCld, hints, aPath);
  		}
  		else
  		{
  			return createTableAlias(aCld, hints, aUserAlias + ALIAS_SEPARATOR + aPath);
  		}
      }
  
      /**
       * Create new TableAlias for path
       * @param cld the class descriptor for the TableAlias
       * @param path the path from the target table of the query to this TableAlias.
       * @param hints a List of Class objects to be used on path expressions
       */
      private TableAlias createTableAlias(ClassDescriptor cld, List hints, String path)
      {
          TableAlias alias;
          boolean lookForExtents = false;
  
          if (!cld.getExtentClasses().isEmpty() && path.length() > 0)
          {
              lookForExtents = true;
          }
  
          String aliasName = String.valueOf(getAliasChar()) + m_aliasCount++; // m_pathToAlias.size();
          alias = new TableAlias(cld, aliasName, lookForExtents, hints);
  
          m_pathToAlias.put(path, alias);
          
          return alias;
      }
  
      /**
       * Create a TableAlias for path or userAlias
       * @param aTable
       * @param aPath
       * @param aUserAlias
       * @return TableAlias
       */
      private TableAlias createTableAlias(String aTable, String aPath, String aUserAlias)
      {
  		if (aUserAlias == null)
  		{
  			return createTableAlias(aTable, aPath);
  		}
  		else
  		{
  			return createTableAlias(aTable, aUserAlias + ALIAS_SEPARATOR + aPath);
  		}
      }
  
      /**
       * Create new TableAlias for path
       * @param table the table name
       * @param path the path from the target table of the query to this TableAlias.
       */
      private TableAlias createTableAlias(String table, String path)
      {
          TableAlias alias;
  
          if (table == null)
          {
              m_logger.warn("Creating TableAlias without table for path: " + path);
          }
  
          String aliasName = String.valueOf(getAliasChar()) + m_aliasCount++; // + m_pathToAlias.size();
          alias = new TableAlias(table, aliasName);
          m_pathToAlias.put(path, alias);
  
          m_logger.debug("createTableAlias2: path: " + path + " tableAlias: " + alias);
  
          return alias;
      }
  
      /**
       * Build Join Tree for SelectionCriteria
       * @param crit
       * @param useOuterJoin
       */
      private void buildJoinTree(SelectionCriteria crit, boolean useOuterJoin)
      {
          // ignore SqlCriteria
          if (crit instanceof SqlCriteria)
          {
              return;
          }
  
          // handle IdentityCriteria as a collection of SelectionCriteria
          if (crit instanceof IdentityCriterion)
          {
              IdentityCriterion idc = (IdentityCriterion) crit;
              Iterator idIter = idc.getCriteriaList().iterator();
              
              while (idIter.hasNext())
              {
                  buildJoinTree((SelectionCriteria) idIter.next(), useOuterJoin);
              }
              
              return;
          }
          
          // do not build join tree for subQuery attribute                  
          if (crit.getAttribute() != null && crit.getAttribute() instanceof String)
          {
  			buildJoinTreeForAttribute((String) crit.getAttribute(), 
  			        useOuterJoin, crit.getUserAlias(), crit.getPathClasses());
          }
          
          // handle the referenced Field
          if (crit instanceof FieldCriteria)
          {
              FieldCriteria cc = (FieldCriteria) crit;
  			buildJoinTreeForAttribute((String) cc.getValue(), useOuterJoin, crit.getUserAlias(), crit.getPathClasses());
          }
              
      }    
          
      /**
       * Build the tree of joins for the given criteria
       */
      private void buildJoinTree(Criteria crit)
      {
          Iterator iter = crit.getIterator();
  
          while (iter.hasNext())
          {
              Object c = iter.next();
              if (c instanceof Criteria)
              {
                  buildJoinTree((Criteria) c);
              }
              else if (c instanceof SelectionCriteria)
              {
                  boolean useOuterJoin = (crit.getType() == Criteria.OR);
                  
                  buildJoinTree((SelectionCriteria) c, useOuterJoin);
              }
              else
              {
                  throw new PersistenceBrokerException("Don't know how to handle Criteria: " + c);
              }
              
          }
      }
  
  	/**
  	 * build the Join-Information for name
  	 * functions and the last segment are removed
  	 * ie: avg(accounts.amount) -> accounts
  	 */
  	private void buildJoinTreeForAttribute(String anAttribName, boolean useOuterJoin, UserAlias aUserAlias, Map pathClasses)
  	{
  		String pathName = SqlHelper.cleanPath(anAttribName);
  		int sepPos = pathName.lastIndexOf(".");
  
  		if (sepPos >= 0)
  		{
  			getTableAlias(pathName.substring(0, sepPos), useOuterJoin, aUserAlias,
  						  new String[]{pathName.substring(sepPos + 1)}, pathClasses);
  		}
  	}
  
      
      /**
       * build the Join-Information if a super reference exists
       *
       * @param left
       * @param cld
       * @param name
       */
      private void buildSuperJoinTree(TableAlias left, ClassDescriptor cld, String name)
      {
          Iterator objRefs = cld.getObjectReferenceDescriptors().iterator();
          while (objRefs.hasNext())
          {
              ObjectReferenceDescriptor objRef = (ObjectReferenceDescriptor) objRefs.next();
              FieldDescriptor[] leftFields = objRef.getForeignKeyFieldDescriptors(cld);
  
              ClassDescriptor refCld = cld.getRepository().getDescriptorFor(objRef.getItemClassName());
              if (objRef.getPersistentField() instanceof AnonymousPersistentFieldForInheritance)
              {
                  TableAlias base_alias = getTableAliasForPath(name, null);
  
                  String aliasName = String.valueOf(getAliasChar()) + m_aliasCount++;
                  TableAlias right = new TableAlias(refCld, aliasName, false, null);
  
                  Join join1to1 = new Join(left, leftFields, right, refCld.getPkFields(), false, "superClass");
                  base_alias.addJoin(join1to1);
  
                  buildSuperJoinTree(right, refCld, name);
              }
          }
      }
  
      //-----------------------------------------------------------------
      // ------------------- Inner classes ------------------------------
      //-----------------------------------------------------------------
  
      /**
       * This class is a helper to return TableAlias and PathInfo
       */
      static final class AttributeInfo
      {
          TableAlias tableAlias;
          PathInfo pathInfo;
      }
  
      /**
       * This class represents one table (possibly with alias) in the SQL query
       */
      final class TableAlias
      {
          Logger logger = LoggerFactory.getLogger(TableAlias.class);
          ClassDescriptor cld; // Is null for indirection table of M:N relation
          String table;
          final String alias;
          List extents = new ArrayList();
          List hints = new ArrayList();
          List joins;
  
          TableAlias(String aTable, String anAlias)
          {
              this.cld = null;
              this.table = aTable;
              this.alias = anAlias;
          }
  
          TableAlias(ClassDescriptor aCld, String anAlias)
          {
              this(aCld, anAlias, false, null);
          }
  
          TableAlias(ClassDescriptor aCld, String anAlias, boolean lookForExtents, List hints)
          {
              this.cld = aCld;
              this.table = aCld.getFullTableName();
              this.alias = anAlias;
              boolean useHintsOnExtents = false;
  
              // BRJ: store alias map of in enclosing class
  			TableAliasHandler.this.m_cldToAlias.put(aCld, this);
  
              //LEANDRO: use hints
              if (hints != null && hints.size() > 0)
              {
                  useHintsOnExtents = true;
              }
  
              logger.debug("TableAlias(): using hints ? " + useHintsOnExtents);
  
              // BRJ : build alias for extents, only one per Table
              if (lookForExtents)
              {
                  ClassDescriptor[] extCLDs = (ClassDescriptor[]) aCld.getRepository().getAllConcreteSubclassDescriptors(
                          aCld).toArray(new ClassDescriptor[0]);
  
                  ClassDescriptor extCd;
                  Class extClass;
                  String extTable;
                  Map extMap = new HashMap(); // only one Alias per Table
                  int firstNonAbstractExtentIndex = 0;
  
                  for (int i = 0; i < extCLDs.length; i++)
                  {
                      extCd = extCLDs[i];
                      extClass = extCd.getClassOfObject();
                      if (useHintsOnExtents && (!hints.contains(extClass)))
                      {
                          //LEANDRO: don't include this class
                          logger.debug("Skipping class [" + extClass + "] from extents List");
                          firstNonAbstractExtentIndex++;
                          continue;
                      }
                      extTable = extCd.getFullTableName();
  
                      // BRJ : Use the first non abstract extent
                      // if the main cld is abstract
                      //logger.debug("cld abstract["+aCld.isAbstract()+"] i["+i+"] index ["+firtsNonAbstractExtentIndex+"]");
                      if (aCld.isAbstract() && i == firstNonAbstractExtentIndex)
                      {
                          this.cld = extCd;
                          this.table = extTable;
                      }
                      else
                      {
                          // Add a new extent entry only if the table of the extent
                          // does not match the table of the 'base' class.
                          if (extMap.get(extTable) == null && !extTable.equals(table))
                          {
                              extMap.put(extTable, new TableAlias(extCd, anAlias + "E" + i, false, hints));
                          }
                      }
                  }
                  extents.addAll(extMap.values());
              }
  
              if (cld == null)
              {
                  throw new PersistenceBrokerSQLException("Table is NULL for alias: " + alias);
              }
          }
  
          ClassDescriptor getClassDescriptor()
          {
              return cld;
          }
  
          String getTableAndAlias()
          {
              return table + " " + alias;
          }
  
          boolean hasExtents()
          {
              return (!extents.isEmpty());
          }
  
          Iterator iterateExtents()
          {
              return extents.iterator();
          }
  
          /**
           * Copy the Alias and all it's extents adding a Postfix
           * Joins are not copied
           * @param aPostfix
           * @return
           */
          TableAlias copy(String aPostfix)
          {
              TableAlias result, temp;
              Iterator iter = iterateExtents();
  
              if (cld == null)
              {
                  result = new TableAlias(table, alias + aPostfix);
              }
              else
              {
                  result = new TableAlias(cld, alias + aPostfix);
              }
  
              while (iter.hasNext())
              {
                  temp = (TableAlias) iter.next();
                  result.extents.add(temp.copy(aPostfix));
              }
  
              return result;
          }
  
          void addJoin(Join join)
          {
              if (joins == null)
              {
                  joins = new ArrayList();
              }
              joins.add(join);
          }
  
          Iterator iterateJoins()
          {
              return joins.iterator();
          }
  
          boolean hasJoins()
          {
              return (joins != null);
          }
  
          public String toString()
          {
              StringBuffer sb = new StringBuffer(1024);
              boolean first = true;
  
              sb.append(getTableAndAlias());
              if (joins != null)
              {
                  sb.append(" [");
                  for (Iterator it = joins.iterator(); it.hasNext();)
                  {
                      Join join = (Join) it.next();
  
                      if (first)
                      {
                          first = false;
                      }
                      else
                      {
                          sb.append(", ");
                      }
                      sb.append("-(");
                      sb.append(join.name);
                      sb.append(")->");
                      sb.append(join.right);
                  }
                  sb.append("]");
              }
              return sb.toString();
          }
  
          public boolean equals(Object obj)
          {
              TableAlias t = (TableAlias) obj;
  
              return table.equals(t.table); // BRJ: check table only
          }
  
          public int hashCode()
          {
              return table.hashCode();
          }
  
      }
  
      /**
       * This class represents join between two TableAliases
       */
      final class Join
      {
          final TableAlias left;
          final String[] leftKeys;
          final TableAlias right;
          final String[] rightKeys;
          final boolean isOuter;
          /** This is the name of the field corresponding to this join */
          final String name;
  
          /**
           * leftKeys and rightKeys should be either FieldDescriptor[] or String[]
           */
          Join(TableAlias left, Object[] leftKeys, TableAlias right, Object[] rightKeys, boolean isOuter, String name)
          {
              this.left = left;
              this.leftKeys = getColumns(leftKeys);
              this.right = right;
              this.rightKeys = getColumns(rightKeys);
              this.isOuter = isOuter;
              this.name = name;
          }
  
          private String[] getColumns(Object[] keys)
          {
              String[] columns = new String[keys.length];
  
              if (keys instanceof FieldDescriptor[])
              {
                  FieldDescriptor[] kd = (FieldDescriptor[]) keys;
                  for (int i = 0; i < columns.length; i++)
                  {
                      columns[i] = kd[i].getColumnName();
                  }
              }
              else
              {
                  for (int i = 0; i < columns.length; i++)
                  {
                      columns[i] = keys[i].toString();
                  }
              }
              return columns;
          }
  
          public boolean equals(Object obj)
          {
              Join j = (Join) obj;
              return name.equals(j.name) && (isOuter == j.isOuter) && right.equals(j.right);
          }
  
          public int hashCode()
          {
              return name.hashCode();
          }
  
          public String toString()
          {
              return left.alias + " -> " + right.alias;
          }
      }
  
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Mime
View raw message