db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b..@apache.org
Subject svn commit: r372946 - in /db/ojb/branches/OJB_1_0_RELEASE: ./ src/java/org/apache/ojb/broker/accesslayer/sql/ src/java/org/apache/ojb/broker/util/ src/test/org/apache/ojb/broker/
Date Fri, 27 Jan 2006 19:00:47 GMT
Author: brj
Date: Fri Jan 27 11:00:27 2006
New Revision: 372946

URL: http://svn.apache.org/viewcvs?rev=372946&view=rev
Log:
Better support for attributes containing expressions ie. sum(0.9 * price * stock)
Backport from OJB 1.x

Modified:
    db/ojb/branches/OJB_1_0_RELEASE/release-notes.txt
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlDeleteByQuery.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/SqlHelper.java
    db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/broker/QueryTest.java

Modified: db/ojb/branches/OJB_1_0_RELEASE/release-notes.txt
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/release-notes.txt?rev=372946&r1=372945&r2=372946&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/release-notes.txt (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/release-notes.txt Fri Jan 27 11:00:27 2006
@@ -18,6 +18,8 @@
 Release 1.0.5
 ---------------------------------------------------------------------
 NEW FEATURES:
+- Better support for attributes containing expressions ie. sum(0.9 * price * stock). 
+  Restriction: All attributes contained in the expressions have to belong to the same table
! 
 
 
 NOTES:

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlDeleteByQuery.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlDeleteByQuery.java?rev=372946&r1=372945&r2=372946&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlDeleteByQuery.java
(original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlDeleteByQuery.java
Fri Jan 27 11:00:27 2006
@@ -16,11 +16,9 @@
  */
 
 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.util.SqlHelper.PathInfo;
 import org.apache.ojb.broker.util.logging.Logger;
 
 /**
@@ -58,30 +56,17 @@
 		return stmt.toString();
 	}
 
-	/* (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)
-	{
-        FieldDescriptor fld = null;
-        String result;
-
-        if (translate)
-        {
-            fld = getFieldDescriptor(aTableAlias, aPathInfo);
-        }
-
-        if (fld != null)
-        {
-            // BRJ : No alias for delete
-            result = fld.getColumnName();
-        }
-        else
-        {
-            result = aPathInfo.column;
-        }
-
-       return result;
-   }
+    /**
+     * Append a Column with alias: A0 name -> A0.name
+     * Do NOT use an alias here.
+     * @param anAlias the TableAlias
+     * @param aColumn name
+     * @param buf
+     */
+    protected void appendColumn(TableAlias anAlias, String aColumn, StringBuffer buf)
+    {
+        // BRJ : No alias for delete
+        buf.append(aColumn);
+    }    
 
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java?rev=372946&r1=372945&r2=372946&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java
(original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java
Fri Jan 27 11:00:27 2006
@@ -22,6 +22,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.StringTokenizer;
 
 import org.apache.ojb.broker.PersistenceBrokerSQLException;
 import org.apache.ojb.broker.accesslayer.JoinSyntaxTypes;
@@ -37,7 +38,6 @@
 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.InCriteria;
 import org.apache.ojb.broker.query.InCriterion;
 import org.apache.ojb.broker.query.LikeCriteria;
 import org.apache.ojb.broker.query.MtoNQuery;
@@ -49,7 +49,6 @@
 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;
 
@@ -170,43 +169,83 @@
         return m_searchCld;
     }
 
+    /**
+     * Get the Attribute info of an attribute. The attribute may be a simple name (ie. price)
or it
+     * may be an expression containing functions or other attributes (ie. sum(price * stock)
).<br>
+     * <b>All embedded attributes must be of the same table !</b>  
+     * <br>
+     * The exploded path contains Strings for the tokens and functions and
+     * SingleAttributeInfo for the attributes.<br>
+     * ie: 0.9 * (price * stock) the attributes price and stock are wrapped
+     * in SingleAttributeInfo the whole rest are Strings
+     * <pre>
+     * [0.9, * , ( sai(price), * , sai(stock), )]
+     * </pre> 
+     * The attribute infos are cached for later use.
+     * 
+     * @param attr the attribute or expression
+     * @param useOuterJoins
+     * @param aUserAlias
+     * @param pathClasses
+     * @return the AttributeInfo of the attribute or expression
+     */
+    protected AttributeInfo getAttributeInfo(String attr, boolean useOuterJoins, UserAlias
aUserAlias, Map pathClasses)
+    {
+        AttributeInfo result = new AttributeInfo(attr);
+
+        StringTokenizer st = SqlHelper.tokenizeAttribute(attr);
+        result = new AttributeInfo(attr);
+
+        while (st.hasMoreTokens())
+        {
+            String token = st.nextToken();
+            if (SqlHelper.isAttribute(token))
+            {
+                result.add(getSingleAttributeInfo(token, useOuterJoins, aUserAlias, pathClasses));
+            }
+            else
+            {
+                result.add(token);
+            }
+        }
+
+        return result;
+    }
+
 	/**
 	 * Return the TableAlias and the PathInfo for an Attribute name<br>
 	 * field names in functions (ie: sum(name) ) are tried to resolve ie: name
 	 * from FIELDDESCRIPTOR , UPPER(name_test) from Criteria<br>
 	 * also resolve pathExpression adress.city or owner.konti.saldo
-	 * @param attr
+	 * @param attrName
 	 * @param useOuterJoins
 	 * @param aUserAlias
 	 * @param pathClasses
 	 * @return ColumnInfo
 	 */
-	protected AttributeInfo getAttributeInfo(String attr, boolean useOuterJoins, UserAlias aUserAlias,
Map pathClasses)
+	protected SingleAttributeInfo getSingleAttributeInfo(String attrName, boolean useOuterJoins,
UserAlias aUserAlias, Map pathClasses)
 	{
-		AttributeInfo result = new AttributeInfo();
 		TableAlias tableAlias;
-		SqlHelper.PathInfo pathInfo = SqlHelper.splitPath(attr);
-		String colName = pathInfo.column;
 		int sp;
 
 		// BRJ:
 		// check if we refer to an attribute in the parent query
 		// this prefix is temporary !
-		if (colName.startsWith(Criteria.PARENT_QUERY_PREFIX) && m_parentStatement != null)
+		if (attrName.startsWith(Criteria.PARENT_QUERY_PREFIX) && m_parentStatement != null)
 		{
-			String[] fieldNameRef = {colName.substring(Criteria.PARENT_QUERY_PREFIX.length())};
-			return m_parentStatement.getAttributeInfo(fieldNameRef[0], useOuterJoins, aUserAlias,
pathClasses);
+			String[] fieldNameRef = {attrName.substring(Criteria.PARENT_QUERY_PREFIX.length())};
+			return m_parentStatement.getSingleAttributeInfo(fieldNameRef[0], useOuterJoins, aUserAlias,
pathClasses);
 		}
 
-		sp = colName.lastIndexOf(".");
+		sp = attrName.lastIndexOf(".");
 		if (sp == -1)
 		{
 			tableAlias = getRoot();
 		}
 		else
 		{
-			String pathName = colName.substring(0, sp);
-			String[] fieldNameRef = {colName.substring(sp + 1)};
+			String pathName = attrName.substring(0, sp);
+			String[] fieldNameRef = {attrName.substring(sp + 1)};
 
 			tableAlias = getTableAlias(pathName, useOuterJoins, aUserAlias, fieldNameRef, pathClasses);
 			/**
@@ -216,12 +255,11 @@
 			 * a path, which means there may be no path separators (,)
 			 * in the pathName.
 			 */
-			if ((tableAlias == null) && (colName.lastIndexOf(".") == -1))
+			if ((tableAlias == null) && (attrName.lastIndexOf(".") == -1))
 			{
 				/**
 				 * pathName might be an alias, so check this first
 				 */
-//				tableAlias = getTableAlias(pathName, useOuterJoins, new UserAlias(pathName, pathName,
pathName), null, pathClasses);
                 tableAlias = getTableAlias(pathName, useOuterJoins, aUserAlias, null, pathClasses);
 			}
 
@@ -229,136 +267,111 @@
 			{
 				// correct column name to match the alias
 				// productGroup.groupName -> groupName
-				pathInfo.column = fieldNameRef[0];
+                attrName = fieldNameRef[0];
 			}
 		}
 
-		result.tableAlias = tableAlias;
-		result.pathInfo = pathInfo;
-		return result;
+		return new SingleAttributeInfo(tableAlias, attrName);
 	}
 
     /**
-     * Answer the column name for alias and path info<br>
-     * if translate try to convert attribute name into column name otherwise use attribute
name<br>
-     * if a FieldDescriptor is found for the attribute name the column name is taken from
-     * there prefixed with the alias (firstname -> A0.F_NAME).
+     * Add the Column to the StringBuffer <br>
+     *
+     * @param aTableAlias
+     * @param aPathInfo
+     * @param translate flag to indicate translation of pathInfo
+     * @param buf
      */
-    protected String getColName(TableAlias aTableAlias, PathInfo aPathInfo, boolean translate)
+    protected void appendColumn(SingleAttributeInfo anAttrInfo, boolean translate, StringBuffer
buf)
     {
-        String result = null;
+        TableAlias tableAlias = anAttrInfo.getTableAlias();
+        String colName = anAttrInfo.getAttribute();
 
         // no translation required, use attribute name
         if (!translate)
         {
-            return aPathInfo.column;
+            buf.append(colName);
+            return;
         }
 
         // BRJ: special alias for the indirection table has no ClassDescriptor 
-        if (aTableAlias.cld == null && M_N_ALIAS.equals(aTableAlias.alias))
+        if (tableAlias != null && tableAlias.cld == null && M_N_ALIAS.equals(tableAlias.alias))
         {
-            return getIndirectionTableColName(aTableAlias, aPathInfo.path);
+            appendColumn(tableAlias, colName, buf);
+            return;
         }
 
         // translate attribute name into column name
-        FieldDescriptor fld = getFieldDescriptor(aTableAlias, aPathInfo);
+        FieldDescriptor fld = getFieldDescriptor(tableAlias, colName);
 
-        if (fld != null)
+        if (fld == null)
         {
-            m_attrToFld.put(aPathInfo.path, fld);
+            buf.append(colName);
+            return;
+        }
 
-            // added to suport the super reference descriptor
-            if (!fld.getClassDescriptor().getFullTableName().equals(aTableAlias.table) &&
aTableAlias.hasJoins())
-            {
-                Iterator itr = aTableAlias.joins.iterator();
-                while (itr.hasNext())
-                {
-                    Join join = (Join) itr.next();
-                    if (join.right.table.equals(fld.getClassDescriptor().getFullTableName()))
-                    {
-                        result = join.right.alias + "." + fld.getColumnName();
-                        break;
-                    }
-                }
+        m_attrToFld.put(anAttrInfo.getParent().getAttribute(), fld);
 
-                if (result == null)
+        // added to suport the super reference descriptor
+        if (!fld.getClassDescriptor().getFullTableName().equals(tableAlias.table) &&
tableAlias.hasJoins())
+        {
+            Iterator itr = tableAlias.joins.iterator();
+            while (itr.hasNext())
+            {
+                Join join = (Join) itr.next();
+                if (join.right.table.equals(fld.getClassDescriptor().getFullTableName()))
                 {
-                    result = aPathInfo.column;
+                    tableAlias = join.right;
+                    colName = fld.getColumnName();
+                    break;
                 }
             }
-            else
-            {
-                result = aTableAlias.alias + "." + fld.getColumnName();
-            }
-        }
-        else if ("*".equals(aPathInfo.column))
-        {
-            result = aPathInfo.column;
         }
         else
         {
-            // throw new IllegalArgumentException("No Field found for : " + aPathInfo.column);
-            result = aPathInfo.column;
+            colName = fld.getColumnName();
         }
 
-        return result;
+        appendColumn(tableAlias, colName, buf);
     }
 
     /**
-     * Add the Column to the StringBuffer <br>
-     *
-     * @param aTableAlias
-     * @param aPathInfo
-     * @param translate flag to indicate translation of pathInfo
+     * Append a Column with alias: A0 name -> A0.name
+     * @param anAlias the TableAlias
+     * @param aColumn name
      * @param buf
-     * @return true if appended
      */
-    protected boolean appendColName(TableAlias aTableAlias, PathInfo aPathInfo, boolean translate,
StringBuffer buf)
+    protected void appendColumn(TableAlias anAlias, String aColumn, StringBuffer buf)
     {
-        String prefix = aPathInfo.prefix;
-        String suffix = aPathInfo.suffix;
-        String colName = getColName(aTableAlias, aPathInfo, translate);
-
-        if (prefix != null) // rebuild function contains (
-        {
-            buf.append(prefix);
-        }
-
-        buf.append(colName);
-
-        if (suffix != null) // rebuild function
-        {
-            buf.append(suffix);
-        }
-
-        return true;
+        buf.append(anAlias.alias);
+        buf.append(".");
+        buf.append(aColumn);
     }
-
+    
     /**
      * Get the FieldDescriptor for the PathInfo
      *
      * @param aTableAlias
-     * @param aPathInfo
+     * @param anAttrName
      * @return FieldDescriptor
      */
-    protected FieldDescriptor getFieldDescriptor(TableAlias aTableAlias, PathInfo aPathInfo)
+    protected FieldDescriptor getFieldDescriptor(TableAlias aTableAlias, String anAttrName)
     {
         FieldDescriptor fld = null;
-        String colName = aPathInfo.column;
 
         if (aTableAlias != null)
         {
-            fld = aTableAlias.cld.getFieldDescriptorByName(colName);
+            fld = aTableAlias.cld.getFieldDescriptorByName(anAttrName);
             if (fld == null)
             {
-                ObjectReferenceDescriptor ord = aTableAlias.cld.getObjectReferenceDescriptorByName(colName);
+                ObjectReferenceDescriptor ord = aTableAlias.cld.getObjectReferenceDescriptorByName(anAttrName);
                 if (ord != null)
                 {
                     fld = getFldFromReference(aTableAlias, ord);
                 }
                 else
                 {
-                    fld = getFldFromJoin(aTableAlias, colName);
+                    fld = getFldFromJoin(aTableAlias, anAttrName);
                 }
             }
         }
@@ -389,7 +402,6 @@
                     {
                         break;
                     }
-
                 }
             }
         }
@@ -432,46 +444,79 @@
     }
 
     /**
+     * Add the Attribute to the StringBuffer.
+     * 
+     * @param attrInfo
+     * @param translate
+     *            flag to indicate translation of attrInfo
+     * @param buf
+     * @return true if appended
+     */
+    protected boolean appendAttribute(AttributeInfo attrInfo, boolean translate, StringBuffer
buf)
+    {
+        Iterator iter = attrInfo.iterator();
+        
+        while (iter.hasNext())
+        {
+            Object element = iter.next();
+            
+            if (element instanceof SingleAttributeInfo)
+            {
+                SingleAttributeInfo sai = (SingleAttributeInfo) element;
+                appendColumn(sai, translate, buf);
+            }
+            else
+            {
+                buf.append(element);
+            }
+        }
+
+        return true;  
+    }
+
+    /**
      * Append the appropriate ColumnName to the buffer<br>
      * if a FIELDDESCRIPTOR is found for the Criteria the colName is taken from
      * there otherwise its taken from Criteria. <br>
      * field names in functions (ie: sum(name) ) are tried to resolve
      * ie: name from FIELDDESCRIPTOR , UPPER(name_test) from Criteria<br>
      * also resolve pathExpression adress.city or owner.konti.saldo
+     *
+     * @param anAttribute
+     * @param useOuterJoins
+     * @param aUserAlias
+     * @param buf
+     * @return true if appended
      */
-	protected boolean appendColName(String attr, boolean useOuterJoins, UserAlias aUserAlias,
StringBuffer buf)
+    protected boolean appendAttribute(String anAttribute, boolean useOuterJoins, UserAlias
aUserAlias, StringBuffer buf)
     {
-		AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias, getQuery().getPathClasses());
-        TableAlias tableAlias = attrInfo.tableAlias;
-
-        return appendColName(tableAlias, attrInfo.pathInfo, (tableAlias != null), buf);
+        AttributeInfo attrInfo = getAttributeInfo(anAttribute, useOuterJoins, aUserAlias,
getQuery().getPathClasses());
+        
+        //BRJ: translate must be true to handle expressions ie. "0.9 * (price * stock)"
+        return appendAttribute(attrInfo, true, buf);        
     }
 
     /**
-     * Append the appropriate ColumnName to the buffer<br>
+     * Append the appropriate aliased ColumnName to the buffer<br>
      * if a FIELDDESCRIPTOR is found for the Criteria the colName is taken from
      * there otherwise its taken from Criteria. <br>
      * field names in functions (ie: sum(name) ) are tried to resolve
      * ie: name from FIELDDESCRIPTOR , UPPER(name_test) from Criteria<br>
      * also resolve pathExpression adress.city or owner.konti.saldo
+     *
+     * @param anAttribute
+     * @param attrAlias column alias
+     * @param useOuterJoins
+     * @param aUserAlias
+     * @param buf
+     * @return true if appended
      */
-	protected boolean appendColName(String attr, String attrAlias, boolean useOuterJoins, UserAlias
aUserAlias,
-            StringBuffer buf)
+    protected boolean appendAttribute(String anAttribute, String attrAlias, boolean useOuterJoins,
+            UserAlias aUserAlias, StringBuffer buf)
     {
-		AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias, getQuery().getPathClasses());
-        TableAlias tableAlias = attrInfo.tableAlias;
-        PathInfo pi = attrInfo.pathInfo;
-
-        if (pi.suffix != null)
-        {
-            pi.suffix = pi.suffix + " as " + attrAlias;
-        }
-        else
-        {
-            pi.suffix = " as " + attrAlias;
-        }
+        String aliasedAttr = anAttribute + " as " + attrAlias;
 
-        return appendColName(tableAlias, pi, true, buf);
+        return appendAttribute(aliasedAttr, useOuterJoins, aUserAlias, buf);
     }
 
     /**
@@ -525,7 +570,7 @@
                 existingColumns.add(cf.name);
                 
                 buf.append(",");
-                appendColName(cf.name, "ojb_col_" + ojb_col, false, null, buf);
+                appendAttribute(cf.name, "ojb_col_" + ojb_col, false, null, buf);
                 ojb_col++;
             }
         }
@@ -589,7 +634,6 @@
          * because we assume you cannot make a relation of the wrong type upon insertion.
Of course,
          * you COULD mess the data up manually and this would cause a problem.
          */
-
         if (clause != null)
         {
             stmt.append(clause.toString());
@@ -606,7 +650,6 @@
                 stmt.append(asSQLStatement(crit));
                 stmt.append(")");
             }
-
         }
     }
 
@@ -697,9 +740,9 @@
      * @param c BetweenCriteria
      * @param buf
      */
-    private void appendBetweenCriteria(TableAlias alias, PathInfo pathInfo, BetweenCriteria
c, StringBuffer buf)
+    private void appendBetweenCriteria(AttributeInfo attrInfo, BetweenCriteria c, StringBuffer
buf)
     {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+        appendAttribute(attrInfo, c.isTranslateAttribute(), buf);
         buf.append(c.getClause());
         appendParameter(c.getValue(), buf);
         buf.append(" AND ");
@@ -722,26 +765,25 @@
      * Answer the SQL-Clause for a FieldCriteria<br>
      * The value of the FieldCriteria will be translated
      *
-     * @param alias
-     * @param pathInfo
+     * @param attrInfo the AttributeInfo 
      * @param c ColumnCriteria
-     * @param buf
+     * @param buf the Buffer to append to
      */
-    private void appendFieldCriteria(TableAlias alias, PathInfo pathInfo, FieldCriteria c,
StringBuffer buf)
+    private void appendFieldCriteria(AttributeInfo attrInfo, FieldCriteria c, StringBuffer
buf)
     {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+        appendAttribute(attrInfo, c.isTranslateAttribute(), buf);
         buf.append(c.getClause());
 
         if (c.isTranslateField())
         {
-			appendColName((String) c.getValue(), false, c.getUserAlias(), buf);
+            appendAttribute((String) c.getValue(), false, c.getUserAlias(), buf);
         }
         else
         {
             buf.append(c.getValue());
         }
     }
-    
+
     /**
      * Get the column name from the indirection table.
      * @param mnAlias 
@@ -762,9 +804,9 @@
      * @param c InCriteria
      * @param buf
      */
-    private void appendInCriteria(TableAlias alias, PathInfo pathInfo, InCriterion c, StringBuffer
buf)
+    private void appendInCriteria(AttributeInfo attrInfo, InCriterion c, StringBuffer buf)
     {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+        appendAttribute(attrInfo, c.isTranslateAttribute(), buf);
         buf.append(c.getClause());
 
         if (c.getValue() instanceof Collection)
@@ -798,9 +840,9 @@
      * @param c NullCriteria
      * @param buf
      */
-    private void appendNullCriteria(TableAlias alias, PathInfo pathInfo, NullCriteria c,
StringBuffer buf)
+    private void appendNullCriteria(AttributeInfo attrInfo, NullCriteria c, StringBuffer
buf)
     {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+        appendAttribute(attrInfo, c.isTranslateAttribute(), buf);
         buf.append(c.getClause());
     }
 
@@ -819,9 +861,9 @@
      * @param c
      * @param buf
      */
-    private void appendSelectionCriteria(TableAlias alias, PathInfo pathInfo, SelectionCriteria
c, StringBuffer buf)
+    private void appendSelectionCriteria(AttributeInfo attrInfo, SelectionCriteria c, StringBuffer
buf)
     {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+        appendAttribute(attrInfo, c.isTranslateAttribute(), buf);
         buf.append(c.getClause());
         appendParameter(c.getValue(), buf);
     }
@@ -832,9 +874,9 @@
      * @param c
      * @param buf
      */
-    private void appendLikeCriteria(TableAlias alias, PathInfo pathInfo, LikeCriteria c,
StringBuffer buf)
+    private void appendLikeCriteria(AttributeInfo attrInfo, LikeCriteria c, StringBuffer
buf)
     {
-        appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
+        appendAttribute(attrInfo, c.isTranslateAttribute(), buf);
         buf.append(c.getClause());
         appendParameter(c.getValue(), buf);
 
@@ -849,23 +891,23 @@
      * @param c SelectionCriteria
      * @param buf
      */
-    protected void appendCriteria(TableAlias alias, PathInfo pathInfo, SelectionCriteria
c, StringBuffer buf)
+    protected void appendCriteria(AttributeInfo attrInfo, SelectionCriteria c, StringBuffer
buf)
     {
         if (c instanceof FieldCriteria)
         {
-            appendFieldCriteria(alias, pathInfo, (FieldCriteria) c, buf);
+            appendFieldCriteria(attrInfo, (FieldCriteria) c, buf);
         }
         else if (c instanceof NullCriteria)
         {
-            appendNullCriteria(alias, pathInfo, (NullCriteria) c, buf);
+            appendNullCriteria(attrInfo, (NullCriteria) c, buf);
         }
         else if (c instanceof BetweenCriteria)
         {
-            appendBetweenCriteria(alias, pathInfo, (BetweenCriteria) c, buf);
+            appendBetweenCriteria(attrInfo, (BetweenCriteria) c, buf);
         }
         else if (c instanceof InCriterion)
         {
-            appendInCriteria(alias, pathInfo, (InCriterion) c, buf);
+            appendInCriteria(attrInfo, (InCriterion) c, buf);
         }
         else if (c instanceof SqlCriteria)
         {
@@ -877,15 +919,28 @@
         }
         else if (c instanceof LikeCriteria)
         {
-            appendLikeCriteria(alias, pathInfo, (LikeCriteria) c, buf);
+            appendLikeCriteria(attrInfo, (LikeCriteria) c, buf);
         }
         else
         {
-            appendSelectionCriteria(alias, pathInfo, c, buf);
+            appendSelectionCriteria(attrInfo, c, buf);
         }
     }
 
     /**
+     * Answer the SQL-Clause for a Query
+     * @param q Query
+     */
+    private void appendSQLClause(Query q, SelectionCriteria c, StringBuffer buf)
+    {
+        buf.append("(");
+        buf.append(getSubQuerySQL(q));
+        buf.append(")");
+        buf.append(c.getClause());
+        appendParameter(c.getValue(), buf);
+    }
+
+    /**
      * Answer the SQL-Clause for a SelectionCriteria
      * If the Criteria references a class with extents an OR-Clause is
      * added for each extent
@@ -903,17 +958,12 @@
         // BRJ : criteria attribute is a query
         if (c.getAttribute() instanceof Query)
         {
-            Query q = (Query) c.getAttribute();
-            buf.append("(");
-            buf.append(getSubQuerySQL(q));
-            buf.append(")");
-            buf.append(c.getClause());
-            appendParameter(c.getValue(), buf);
+            appendSQLClause((Query) c.getAttribute(), c, buf);
             return;
         }
 
 		AttributeInfo attrInfo = getAttributeInfo((String) c.getAttribute(), false, c.getUserAlias(),
c.getPathClasses());
-        TableAlias alias = attrInfo.tableAlias;
+        TableAlias alias = attrInfo.getTableAlias();
 
         if (alias != null)
         {
@@ -923,28 +973,27 @@
             {
                 // BRJ : surround with braces if alias has extents
                 buf.append("(");
-                appendCriteria(alias, attrInfo.pathInfo, c, buf);
+                appendCriteria(attrInfo, c, buf);
 
                 c.setNumberOfExtentsToBind(alias.extents.size());
-                Iterator iter = alias.iterateExtents();
-                while (iter.hasNext())
+                for (int i = 0;i < alias.extents.size(); i++)
                 {
-                    TableAlias tableAlias = (TableAlias) iter.next();
                     buf.append(" OR ");
-                    appendCriteria(tableAlias, attrInfo.pathInfo, c, buf);
+                    attrInfo.useNextExtent();     
+                    appendCriteria(attrInfo, c, buf);                    
                 }
                 buf.append(")");
             }
             else
             {
                 // no extents
-                appendCriteria(alias, attrInfo.pathInfo, c, buf);
+                appendCriteria(attrInfo, c, buf);
             }
         }
         else
         {
             // alias null
-            appendCriteria(alias, attrInfo.pathInfo, c, buf);
+            appendCriteria(attrInfo, c, buf);
         }
 
     }
@@ -1019,7 +1068,6 @@
         Object[] prevKeys;
         Object[] keys;
         ArrayList descriptors;
-        boolean outer = useOuterJoins;
         int pathLength;
         List hintClasses = null;       
         String pathAlias = aUserAlias == null ? null : aUserAlias.getAlias(aPath);
@@ -1057,6 +1105,7 @@
 		pathLength = descriptors.size();
 		for (int i = 0; i < pathLength; i++)
 		{
+            boolean outer = useOuterJoins;
 			if (!(descriptors.get(i) instanceof ObjectReferenceDescriptor))
 			{
 				// only use Collection- and ObjectReferenceDescriptor
@@ -1161,7 +1210,7 @@
 			{
 				curr = createTableAlias(cld, attrPath, pathAlias, hintClasses);
 
-				outer = outer || (curr.cld == prev.cld) || curr.hasExtents() || useOuterJoins;
+				outer = outer || (curr.cld == prev.cld) || curr.hasExtents();
 				addJoin(prev, prevKeys, curr, keys, outer, attr);
 
 				buildSuperJoinTree(curr, cld, aPath, outer);
@@ -1504,7 +1553,7 @@
             }
             else
             {            
-                appendColName(cf.name, false, null, buf);
+                appendAttribute(cf.name, false, null, buf);
             }
             
             if (!cf.isAscending)
@@ -1536,7 +1585,7 @@
                 buf.append(",");
             }
 
-            appendColName(cf.name, false, null, buf);
+            appendAttribute(cf.name, false, null, buf);
         }
     }
 
@@ -1897,10 +1946,127 @@
      */
     static final class AttributeInfo
     {
-        TableAlias tableAlias;
-        PathInfo pathInfo;
+        private String m_attribute; // For information only 
+        private List m_elements = new ArrayList(); // List of String and SingleAttributeInfo
+        private int m_extentAliasIndex = 0; // which alias to use
+
+        AttributeInfo(String anAttribute)
+        {
+            m_attribute = anAttribute;
+        }
+
+        /**
+         * Answer the TableAlias of the <b>first</b> SingleAttributeInfo. 
+         * @return TableAlias
+         */
+        TableAlias getTableAlias()
+        {
+            TableAlias result = null;
+            Iterator iter = m_elements.iterator();
+            while (iter.hasNext())
+            {
+                Object element = iter.next();
+                if (element instanceof SingleAttributeInfo)
+                {
+                    result = ((SingleAttributeInfo) element).m_tableAlias;
+                    break;
+                }
+            }
+
+            return result;
+        }
+
+        /**
+         * Add a SingleAttributeInfo and set it's parent.
+         * @param sai SingleAttributeInfo
+         */
+        void add(SingleAttributeInfo sai)
+        {
+            sai.m_parent = this;
+            m_elements.add(sai);
+        }
+
+        /**
+         * Add a simple String.
+         * @param str
+         */
+        void add(String str)
+        {
+            m_elements.add(str);
+        }
+
+        Iterator iterator()
+        {
+            return m_elements.iterator();
+        }
+        
+        String getAttribute()
+        {
+            return m_attribute;
+        }
+
+
+        /**
+         * Increment the extentIndex.
+         */
+        void useNextExtent()
+        {
+            m_extentAliasIndex++;
+        }
+
+        /**
+         * Reset the extentIndex.
+         */
+        void reset()
+        {
+            m_extentAliasIndex = 0;
+        }  
     }
+    
+    /**
+     * Helper Class containing a TableAlias and an Attribute.
+     * ie: A0.emp_firstname
+     */
+    static final class SingleAttributeInfo
+    {
+        private TableAlias m_tableAlias;
+        private String m_attribute;
+        private AttributeInfo m_parent;
+
+        SingleAttributeInfo(TableAlias aTableAlias, String anAttribute)
+        {
+            m_tableAlias = aTableAlias;
+            m_attribute = anAttribute;
+        }
+
+        /**
+         * Answer the TableAlias based on extentAliasIndex of the parent AttributeInfo.
+         * @return the TableAlias 
+         */
+        TableAlias getTableAlias()
+        {
+            TableAlias result = m_tableAlias;
+            int aliasIndex = m_parent.m_extentAliasIndex;
+
+            if (aliasIndex > 0)
+            {
+                result = (TableAlias) m_tableAlias.extents.get(aliasIndex - 1);
+            }
+
+            return result;
+        }
 
+        String getAttribute()
+        {
+            return m_attribute;
+        }
+        
+        AttributeInfo getParent()
+        {
+            return m_parent;
+        }
+    }
+    
     /**
      * This class represents one table (possibly with alias) in the SQL query
      */

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java?rev=372946&r1=372945&r2=372946&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
(original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
Fri Jan 27 11:00:27 2006
@@ -258,7 +258,7 @@
             {
                 buf.append(",");
             }
-            appendColName(columns[i], false, null, buf);
+            appendAttribute(columns[i], false, null, buf);
             columnList.add(columns[i]);
         }
         return columnList;

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/SqlHelper.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/SqlHelper.java?rev=372946&r1=372945&r2=372946&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/SqlHelper.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/SqlHelper.java Fri
Jan 27 11:00:27 2006
@@ -16,6 +16,7 @@
  */
 
 import java.sql.SQLException;
+import java.util.StringTokenizer;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.ojb.broker.PersistenceBrokerException;
@@ -29,105 +30,68 @@
  */
 public class SqlHelper
 {
+    /** delimiters to tokenize attributes. */
+    private static final String DELIMITERS = "( ),+-/*";
+    
+    /** do not try to reslve these. */
+    private static final String NO_ATTRIBUTES = "count,min,max,avg,sum,upper,lower,distinct,as";
+
     /** define the name of the pseudo column holding the class to be instantiated. */
     public static final String OJB_CLASS_COLUMN = "OJB_CLAZZ"; 
 
     /**
-	 * Helper Class for a split column <br>
-	 * ie: sum (distinct amount) as theAmount
-	 * 
-	 * <pre>
-	 *  prefix = 'sum (distinct '
-	 *  column = 'amount'
-	 *  suffix = ') as theAmount'
-	 * </pre>
-	 */
-	public static final class PathInfo
-	{
-		public String column;
-		public String prefix;
-		public String suffix;
-        public final String path;  //original Path
+     * Answer a StringTokenizer for anAttribute.
+     * @param anAttribute the attribute to tokenize
+     * @return StringTokenizer
+     */
+    public static StringTokenizer tokenizeAttribute(String anAttribute)
+    {
 
-		PathInfo(String aPath, String aPrefix, String aColumn, String aSuffix)
+        return new StringTokenizer(anAttribute, DELIMITERS, true);
+    }
+    
+    /**
+     * Answer <em>true</em> if anAttribute is not a token or a 'function'.
+     * @param anAttribute the attribute to check
+     * @return The result of the attribute check.
+     */
+    public static boolean isAttribute(String anAttribute)
+    {
+        // look for delimiters       
+        if (DELIMITERS.indexOf(anAttribute) >= 0)
         {
-            path = aPath;
-			column = aColumn;
-			prefix = aPrefix;
-			suffix = aSuffix;
-		}
-	}
-
-	/**
-	 * remove functions and () from path <br>
-	 * ie: avg(amount) -> amount <br>
-	 * ie: sum (accounts.amount) -> accounts.amount <br>
-	 * ie: count(distinct id) as theCount-> id <br>
-	 * 
-	 * @param aPath
-	 *            the path to the attribute
-	 */
-	public static String cleanPath(String aPath)
-	{
-		return splitPath(aPath).column;
-	}
+            return false;
+        }
+        //TODO: should be platform specific !?
+        return NO_ATTRIBUTES.indexOf(anAttribute.toLowerCase()) < 0;
+    }
 
     /**
-     * Split a path into column , prefix and suffix, the prefix contains all
-     * info up to the column <br>
-     * ie: avg(amount) -> amount , avg( , )<br>
-     * ie: sum (accounts.amount) as theSum -> accounts.amount , sum( , ) as
-     * theSum <br>
-     * ie: count( distinct id ) as bla -> id , count(distinct , ) as bla <br>
-     * Supports simple expressions ie: price * 1.05
+     * remove functions and () from path <br>
+     * ie: avg(amount) -> amount <br>
+     * ie: sum (accounts.amount) -> accounts.amount <br>
+     * ie: count(distinct id) as theCount-> id <br>
      * 
-     * TODO: cannot resolve multiple attributes in expression 
-     * ie: price - bonus
-     * 
-     * @param aPath
-     * @return PathInfo
+     * @param aPath the path to the attribute
      */
-    public static PathInfo splitPath(String aPath)
+    public static String cleanPath(String aPath)
     {
-        String prefix = null;
-        String suffix = null;
-        String colName = aPath;
- 
-        if (aPath == null)
+        StringTokenizer st = new StringTokenizer(aPath, DELIMITERS, false);
+        String result = aPath;
+        
+        while (st.hasMoreTokens())
         {
-            return new PathInfo(null, null, null, null);
+            String token = st.nextToken();
+            if (isAttribute(token))
+            {
+                result = token.trim();
+                break;
+            }
         }
 
-        // ignore leading ( and trailing ) ie: sum(avg(col1))
-        int braceBegin = aPath.lastIndexOf("(");
-        int braceEnd = aPath.indexOf(")");
-        int opPos = StringUtils.indexOfAny(aPath, "+-/*");
-
-        if (braceBegin >= 0 && braceEnd >= 0 && braceEnd > braceBegin)
-        {
-            int colBegin;
-            int colEnd;
-            String betweenBraces;
-
-            betweenBraces = aPath.substring(braceBegin + 1, braceEnd).trim();
-            // look for ie 'distinct name'
-            colBegin = betweenBraces.indexOf(" ");
-            // look for multiarg function like to_char(col,'format_mask')
-            colEnd = betweenBraces.indexOf(",");
-            colEnd = colEnd > 0 ? colEnd : betweenBraces.length();
-            prefix = aPath.substring(0, braceBegin + 1) + betweenBraces.substring(0, colBegin
+ 1);
-            colName = betweenBraces.substring(colBegin + 1, colEnd);
-            suffix = betweenBraces.substring(colEnd) + aPath.substring(braceEnd);
-        }
-        else if (opPos >= 0)
-        {
-            colName = aPath.substring(0, opPos).trim();
-            suffix = aPath.substring(opPos);
-        }
-        
-        return new PathInfo(aPath, prefix, colName.trim(), suffix);
+        return result;
     }
-    
+
     /**
      * Returns the name of the class to be instantiated.
      * @param rs the Resultset

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/broker/QueryTest.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/broker/QueryTest.java?rev=372946&r1=372945&r2=372946&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/broker/QueryTest.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/broker/QueryTest.java Fri Jan
27 11:00:27 2006
@@ -1714,7 +1714,7 @@
     /**
      * ReportQuery with Expression in column need to add table alias to the field (price)
      **/
-    public void testReportQueryExpressionInStatement()
+    public void testReportQueryExpressionInStatement1()
     {
         // TODO: Resolve attributes of expressions
         if(ojbSkipKnownIssueProblem("Resolve attributes of expressions")) return;
@@ -1729,7 +1729,23 @@
         assertTrue("Bad query generated. the 'price' field has not table prefix. SQL Output:
" + sql, sql
                 .equalsIgnoreCase("SELECT A0.Artikel_Nr,A0.Einzelpreis+10 FROM Artikel A0"));
     }
-     
+
+    /**
+     * ReportQuery with Expression in column need to add table alias to the field (price)
+     **/
+    public void testReportQueryExpressionInStatement2()
+    {
+        Criteria crit = new Criteria();
+        ReportQueryByCriteria q = QueryFactory.newReportQuery(Article.class, crit);
+        q.setAttributes(new String[]{"articleId", "0.9 * (price * stock)"});
+        ClassDescriptor cd = broker.getClassDescriptor(q.getBaseClass());
+        SqlGenerator sqlg = broker.serviceSqlGenerator();
+        String sql = sqlg.getPreparedSelectStatement(q, cd).getStatement();
+        
+        assertTrue("Bad query generated. SQL Output: " + sql, sql
+                .equalsIgnoreCase("SELECT A0.Artikel_Nr,0.9 * (A0.Einzelpreis * A0.Lagerbestand)
FROM Artikel A0"));
+    }
+
 
     /**
      * Test pathExpression and Extents



---------------------------------------------------------------------
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