[hibernate-commits] Hibernate SVN: r21065 - annotations/patches/JBPAPP-6940/jdbc and 12 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Aug 30 12:55:40 EDT 2012


Author: brmeyer
Date: 2012-08-30 12:55:39 -0400 (Thu, 30 Aug 2012)
New Revision: 21065

Added:
   core/patches/JBPAPP-6940/grammar/order-by-render.g
   core/patches/JBPAPP-6940/grammar/order-by.g
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/CollationSpecification.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/ColumnMapper.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/ColumnReference.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/Factory.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/FormulaReference.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/Node.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/NodeSupport.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByAliasResolver.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragment.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentParser.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentRenderer.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentTranslator.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByTranslation.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderingSpecification.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SortKey.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SortSpecification.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SqlValueReference.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/TranslationContext.java
Modified:
   annotations/patches/JBPAPP-6940/
   annotations/patches/JBPAPP-6940/jdbc/
   annotations/patches/JBPAPP-6940/src/java/org/hibernate/cfg/annotations/CollectionBinder.java
   annotations/patches/JBPAPP-6940/src/test/org/hibernate/test/annotations/manytomany/ManyToManyTest.java
   annotations/patches/JBPAPP-6940/src/test/org/hibernate/test/annotations/onetomany/OneToManyTest.java
   core/patches/JBPAPP-6940/
   core/patches/JBPAPP-6940/build.xml
   core/patches/JBPAPP-6940/src/org/hibernate/hql/ast/util/ASTPrinter.java
   core/patches/JBPAPP-6940/src/org/hibernate/persister/collection/AbstractCollectionPersister.java
   core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/AbstractEntityPersister.java
   core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java
   core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/Loadable.java
   core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/Queryable.java
   core/patches/JBPAPP-6940/src/org/hibernate/sql/Template.java
   core/patches/JBPAPP-6940/src/org/hibernate/util/StringHelper.java
Log:
JBPAPP-6940 ManyToManyTest.testOrderByContractor fails on DB2 and Sybase


Property changes on: annotations/patches/JBPAPP-6940
___________________________________________________________________
Added: svn:ignore
   + .settings
build
.classpath
.project



Property changes on: annotations/patches/JBPAPP-6940/jdbc
___________________________________________________________________
Added: svn:ignore
   + db2jcc_license_cu.jar
db2jcc.jar
sqlj.zip


Modified: annotations/patches/JBPAPP-6940/src/java/org/hibernate/cfg/annotations/CollectionBinder.java
===================================================================
--- annotations/patches/JBPAPP-6940/src/java/org/hibernate/cfg/annotations/CollectionBinder.java	2012-08-30 16:52:35 UTC (rev 21064)
+++ annotations/patches/JBPAPP-6940/src/java/org/hibernate/cfg/annotations/CollectionBinder.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -1,12 +1,10 @@
 package org.hibernate.cfg.annotations;
 
-import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
-import java.util.StringTokenizer;
+
 import javax.persistence.AttributeOverride;
 import javax.persistence.AttributeOverrides;
 import javax.persistence.Embeddable;
@@ -78,9 +76,7 @@
 import org.hibernate.mapping.ManyToOne;
 import org.hibernate.mapping.PersistentClass;
 import org.hibernate.mapping.Property;
-import org.hibernate.mapping.Selectable;
 import org.hibernate.mapping.SimpleValue;
-import org.hibernate.mapping.SingleTableSubclass;
 import org.hibernate.mapping.Table;
 import org.hibernate.util.StringHelper;
 
@@ -817,186 +813,33 @@
 		}
 	}
 
-	private static String buildOrderByClauseFromHql(String hqlOrderBy, PersistentClass associatedClass, String role) {
-		String orderByString = null;
-		if ( hqlOrderBy != null ) {
-			List<String> properties = new ArrayList<String>();
-			List<String> ordering = new ArrayList<String>();
-			StringBuilder orderByBuffer = new StringBuilder();
-			if ( hqlOrderBy.length() == 0 ) {
+	private static String buildOrderByClauseFromHql(String orderByFragment, PersistentClass associatedClass, String role) {
+		if ( orderByFragment != null ) {
+			if ( orderByFragment.length() == 0 ) {
 				//order by id
-				Iterator it = associatedClass.getIdentifier().getColumnIterator();
-				while ( it.hasNext() ) {
-					Selectable col = (Selectable) it.next();
-					orderByBuffer.append( col.getText() ).append( " asc" ).append( ", " );
-				}
+				return "id asc";
 			}
-			else {
-				StringTokenizer st = new StringTokenizer( hqlOrderBy, " ,", false );
-				String currentOrdering = null;
-				//FIXME make this code decent
-				while ( st.hasMoreTokens() ) {
-					String token = st.nextToken();
-					if ( isNonPropertyToken( token ) ) {
-						if ( currentOrdering != null ) {
-							throw new AnnotationException(
-									"Error while parsing HQL orderBy clause: " + hqlOrderBy
-											+ " (" + role + ")"
-							);
-						}
-						currentOrdering = token;
-					}
-					else {
-						//Add ordering of the previous
-						if ( currentOrdering == null ) {
-							//default ordering
-							ordering.add( "asc" );
-						}
-						else {
-							ordering.add( currentOrdering );
-							currentOrdering = null;
-						}
-						properties.add( token );
-					}
-				}
-				ordering.remove( 0 ); //first one is the algorithm starter
-				// add last one ordering
-				if ( currentOrdering == null ) {
-					//default ordering
-					ordering.add( "asc" );
-				}
-				else {
-					ordering.add( currentOrdering );
-					currentOrdering = null;
-				}
-				int index = 0;
-
-				for (String property : properties) {
-					Property p = BinderHelper.findPropertyByName( associatedClass, property );
-					if ( p == null ) {
-						throw new AnnotationException(
-								"property from @OrderBy clause not found: "
-										+ associatedClass.getEntityName() + "." + property
-						);
-					}
-					PersistentClass pc = p.getPersistentClass();
-					String table;
-					if ( pc == null ) {
-						//we are touching a @IdClass property, the pc is not set
-						//this means pc == associatedClass
-						//TODO check whether @ManyToOne @JoinTable in @IdClass used for @OrderBy works: doh!
-						table = "";
-					}
-					else if (pc == associatedClass
-							|| (associatedClass instanceof SingleTableSubclass && pc
-									.getMappedClass().isAssignableFrom(
-											associatedClass.getMappedClass()))) {
-						table = "";
-					} else {
-						table = pc.getTable().getQuotedName() + ".";
-					}
-					Iterator propertyColumns = p.getColumnIterator();
-					while ( propertyColumns.hasNext() ) {
-						Selectable column = (Selectable) propertyColumns.next();
-						orderByBuffer.append( table )
-								.append( column.getText() )
-								.append( " " )
-								.append( ordering.get( index ) )
-								.append( ", " );
-					}
-					index++;
-				}
+			else if ( "desc".equals( orderByFragment ) ) {
+				return "id desc";
 			}
-			orderByString = orderByBuffer.substring( 0, orderByBuffer.length() - 2 );
 		}
-		return orderByString;
+		return orderByFragment;
 	}
 
-	private static String buildOrderByClauseFromHql(String hqlOrderBy, Component component, String role) {
-		String orderByString = null;
-		if ( hqlOrderBy != null ) {
-			List<String> properties = new ArrayList<String>();
-			List<String> ordering = new ArrayList<String>();
-			StringBuilder orderByBuffer = new StringBuilder();
-			if ( hqlOrderBy.length() == 0 ) {
-				//TODO : Check that. Maybe order by key for maps
+	private static String adjustUserSuppliedValueCollectionOrderingFragment(String orderByFragment) {
+		if ( orderByFragment != null ) {
+			// NOTE: "$element$" is a specially recognized collection property recognized by the collection persister
+			if ( orderByFragment.length() == 0 ) {
+				//order by element
+				return "$element$ asc";
 			}
-			else {
-				StringTokenizer st = new StringTokenizer( hqlOrderBy, " ,", false );
-				String currentOrdering = null;
-				//FIXME make this code decent
-				while ( st.hasMoreTokens() ) {
-					String token = st.nextToken();
-					if ( isNonPropertyToken( token ) ) {
-						if ( currentOrdering != null ) {
-							throw new AnnotationException(
-									"Error while parsing HQL orderBy clause: " + hqlOrderBy
-											+ " (" + role + ")"
-							);
-						}
-						currentOrdering = token;
-					}
-					else {
-						//Add ordering of the previous
-						if ( currentOrdering == null ) {
-							//default ordering
-							ordering.add( "asc" );
-						}
-						else {
-							ordering.add( currentOrdering );
-							currentOrdering = null;
-						}
-						properties.add( token );
-					}
-				}
-				ordering.remove( 0 ); //first one is the algorithm starter
-				// add last one ordering
-				if ( currentOrdering == null ) {
-					//default ordering
-					ordering.add( "asc" );
-				}
-				else {
-					ordering.add( currentOrdering );
-					currentOrdering = null;
-				}
-				int index = 0;
-
-				for (String property : properties) {
-					Property p = component.getProperty( property );
-					if ( p == null ) {
-						throw new AnnotationException(
-								"property from @OrderBy clause not found: "
-										+ role + "." + property
-						);
-					}
-
-					Iterator propertyColumns = p.getColumnIterator();
-					while ( propertyColumns.hasNext() ) {
-						Selectable column = (Selectable) propertyColumns.next();
-						orderByBuffer.append( column.getText() )
-								.append( " " )
-								.append( ordering.get( index ) )
-								.append( ", " );
-					}
-					index++;
-				}
-
-				if ( orderByBuffer.length() >= 2 ) {
-					orderByString = orderByBuffer.substring( 0, orderByBuffer.length() - 2 );
-				}
+			else if ( "desc".equals( orderByFragment ) ) {
+				return "$element$ desc";
 			}
 		}
-		return orderByString;
+		return orderByFragment;
 	}
 
-	private static boolean isNonPropertyToken(String token) {
-		if ( " ".equals( token ) ) return true;
-		if ( ",".equals( token ) ) return true;
-		if ( token.equalsIgnoreCase( "desc" ) ) return true;
-		if ( token.equalsIgnoreCase( "asc" ) ) return true;
-		return false;
-	}
-
 	private static SimpleValue buildCollectionKey(
 			Collection collValue, Ejb3JoinColumn[] joinColumns, boolean cascadeDeleteEnabled,
 			XProperty property, ExtendedMappings mappings
@@ -1265,7 +1108,7 @@
 
 				if ( StringHelper.isNotEmpty( hqlOrderBy ) ) {
 					String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
-					String orderBy = buildOrderByClauseFromHql( hqlOrderBy, component, path );
+					String orderBy = adjustUserSuppliedValueCollectionOrderingFragment( hqlOrderBy );
 					if ( orderBy != null ) {
 						collValue.setOrderBy( orderBy );
 					}
@@ -1296,6 +1139,10 @@
 				elementBinder.setColumns( elementColumns );
 				elementBinder.setType( property, elementClass );
 				collValue.setElement( elementBinder.make() );
+				String orderBy = adjustUserSuppliedValueCollectionOrderingFragment( hqlOrderBy );
+				if ( orderBy != null ) {
+					collValue.setOrderBy( orderBy );
+				}
 			}
 		}
 

Modified: annotations/patches/JBPAPP-6940/src/test/org/hibernate/test/annotations/manytomany/ManyToManyTest.java
===================================================================
--- annotations/patches/JBPAPP-6940/src/test/org/hibernate/test/annotations/manytomany/ManyToManyTest.java	2012-08-30 16:52:35 UTC (rev 21064)
+++ annotations/patches/JBPAPP-6940/src/test/org/hibernate/test/annotations/manytomany/ManyToManyTest.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -14,10 +14,6 @@
 import org.hibernate.JDBCException;
 import org.hibernate.Session;
 import org.hibernate.Transaction;
-import org.hibernate.dialect.MySQLDialect;
-import org.hibernate.dialect.Oracle8iDialect;
-import org.hibernate.dialect.PostgreSQLDialect;
-import org.hibernate.dialect.SQLServerDialect;
 import org.hibernate.test.annotations.TestCase;
 
 /**
@@ -258,38 +254,9 @@
 		s.close();
 
 	}
-	/**
-	 * ANN-625
-	 * 
-	 * @throws Exception in case the test fails.
-	 * 
-	 * This test only works against databases which allow a mixed usage of
-     * table names and table aliases. The generated SQL for this test is:
-	 * 
-	 * 	   select
-	 *         contractor0_.EMPLOYER_ID as EMPLOYER1_1_,
-	 *         contractor0_.CONTRACTOR_ID as CONTRACTOR2_1_,
-	 *         contractor1_.id as id2_0_,
-	 *         contractor1_.fld_name as fld3_2_0_,
-	 *         contractor1_.hourlyRate as hourlyRate2_0_ 
-	 *     from
-	 *         EMPLOYER_CONTRACTOR contractor0_ 
-	 *     left outer join
-	 *         Employee contractor1_ 
-	 *             on contractor0_.CONTRACTOR_ID=contractor1_.id 
-	 *     where
-	 *         contractor0_.EMPLOYER_ID=? 
-	 *     order by
-	 *         Employee.fld_name desc
-	 * 
-	 * 
-	 */
-// HHH-3577 JBPAPP-1123
+	
+	// HHH-4394
 	public void testOrderByContractor() throws Exception {
-		if(getDialect() instanceof MySQLDialect || getDialect() instanceof PostgreSQLDialect || getDialect() instanceof SQLServerDialect|| getDialect() instanceof Oracle8iDialect){
-			log.warn("skip test testOrderByContractor due to JBPAPP-1123");
-			return;
-		}
 		Session s;
 		Transaction tx;
 		s = openSession();

Modified: annotations/patches/JBPAPP-6940/src/test/org/hibernate/test/annotations/onetomany/OneToManyTest.java
===================================================================
--- annotations/patches/JBPAPP-6940/src/test/org/hibernate/test/annotations/onetomany/OneToManyTest.java	2012-08-30 16:52:35 UTC (rev 21064)
+++ annotations/patches/JBPAPP-6940/src/test/org/hibernate/test/annotations/onetomany/OneToManyTest.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -79,10 +79,16 @@
 		s.flush();
 		s.clear();
 
-		//testing @OrderBy with explicit values including Formula
+		// Assert the primary key value relationship amongst the 3 streets...
+		assertTrue( rochechoir.getId() < chmpsElysees.getId() );
+		assertTrue( chmpsElysees.getId() < grandeArmee.getId() );
 		paris = (City) s.get( City.class, paris.getId() );
+		
+		// City.streets is defined to be ordered by name primarily...
 		assertEquals( 3, paris.getStreets().size() );
 		assertEquals( chmpsElysees.getStreetName(), paris.getStreets().get( 0 ).getStreetName() );
+		assertEquals( grandeArmee.getStreetName(), paris.getStreets().get( 1 ).getStreetName() );
+		// City.mainStreets is defined to be ordered by street id
 		List<Street> mainStreets = paris.getMainStreets();
 		assertEquals( 2, mainStreets.size() );
 		Integer previousId = new Integer( -1 );
@@ -381,7 +387,8 @@
 		tx.commit();
 		s.close();
 	}
-	//known issue JBPAPP-1123 HHH-3577
+	
+	// HHH-4394
 	public void testOrderByOnSuperclassProperty() {
 		if(getDialect() instanceof MySQLDialect || getDialect() instanceof PostgreSQLDialect || getDialect() instanceof SQLServerDialect|| getDialect() instanceof Oracle8iDialect){
 			log.warn("skip test testOrderByContractor due to JBPAPP-1123");


Property changes on: core/patches/JBPAPP-6940
___________________________________________________________________
Added: svn:ignore
   + .settings
build
.classpath
.project


Modified: core/patches/JBPAPP-6940/build.xml
===================================================================
--- core/patches/JBPAPP-6940/build.xml	2012-08-30 16:52:35 UTC (rev 21064)
+++ core/patches/JBPAPP-6940/build.xml	2012-08-30 16:55:39 UTC (rev 21065)
@@ -48,6 +48,7 @@
     <property name="dir.out.test-classes" value="${dir.build}/testclasses"/>
     <property name="dir.out.generated-source" value="${dir.build}/gensrc"/>
     <property name="dir.out.antlr-package" value="${dir.out.generated-source}/org/hibernate/hql/antlr"/>
+    <property name="dir.out.antlr-package.order-by" value="${dir.out.generated-source}/org/hibernate/sql/ordering/antlr"/>
     <property name="dir.out.junit" value="${dir.build}/testout"/>
     <property name="dir.out.junit-reports" value="${dir.build}/test-reports"/>
     <property name="dir.out.perf-test" value="${dir.build}/testout-perf"/>
@@ -170,7 +171,8 @@
 
     <target name="antlr" depends="init.antlr" unless="antlr.isUpToDate" description="Generate ANTLR parsers.">
         <mkdir dir="${dir.out.antlr-package}"/>
-        <antlr target="${dir.grammar}/hql.g" outputdirectory="${dir.out.antlr-package}">
+    	<mkdir dir="${dir.out.antlr-package.order-by}"/>
+    	<antlr target="${dir.grammar}/hql.g" outputdirectory="${dir.out.antlr-package}">
             <classpath refid="path.lib"/>
         </antlr>
         <antlr target="${dir.grammar}/hql-sql.g" outputdirectory="${dir.out.antlr-package}">
@@ -179,6 +181,12 @@
         <antlr target="${dir.grammar}/sql-gen.g" outputdirectory="${dir.out.antlr-package}">
             <classpath refid="path.lib"/>
         </antlr>
+        <antlr target="${dir.grammar}/order-by.g" outputdirectory="${dir.out.antlr-package.order-by}">
+            <classpath refid="path.lib"/>
+        </antlr>
+        <antlr target="${dir.grammar}/order-by-render.g" outputdirectory="${dir.out.antlr-package.order-by}">
+            <classpath refid="path.lib"/>
+        </antlr>
         <touch file="${dir.out.antlr-package}/.antlr_run"/>
     </target>
 

Added: core/patches/JBPAPP-6940/grammar/order-by-render.g
===================================================================
--- core/patches/JBPAPP-6940/grammar/order-by-render.g	                        (rev 0)
+++ core/patches/JBPAPP-6940/grammar/order-by-render.g	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,92 @@
+header
+{
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.sql.ordering.antlr;
+}
+/**
+ * Antlr grammar for rendering <tt>ORDER_BY</tt> trees as described by the {@link OrderByFragmentParser}
+
+ * @author Steve Ebersole
+ */
+class GeneratedOrderByFragmentRenderer extends TreeParser;
+
+options {
+	importVocab=OrderByTemplate;
+	buildAST=false;
+}
+
+{
+    // the buffer to which we write the resulting SQL.
+	private StringBuilder buffer = new StringBuilder();
+
+	protected void out(String text) {
+	    buffer.append( text );
+	}
+
+	protected void out(AST ast) {
+	    buffer.append( ast.getText() );
+	}
+
+    /*package*/ String getRenderedFragment() {
+        return buffer.toString();
+    }
+}
+
+orderByFragment
+    : #(
+        ORDER_BY sortSpecification ( {out(", ");} sortSpecification)*
+    )
+    ;
+
+sortSpecification
+    : #(
+        SORT_SPEC sortKeySpecification (collationSpecification)? (orderingSpecification)?
+    )
+    ;
+
+sortKeySpecification
+    : #(SORT_KEY sortKey)
+    ;
+
+sortKey
+    : i:IDENT {
+        out( #i );
+    }
+    ;
+
+collationSpecification
+    : c:COLLATE {
+        out( " collate " );
+        out( c );
+    }
+    ;
+
+orderingSpecification
+    : o:ORDER_SPEC {
+        out( " " );
+        out( #o );
+    }
+    ;
\ No newline at end of file

Added: core/patches/JBPAPP-6940/grammar/order-by.g
===================================================================
--- core/patches/JBPAPP-6940/grammar/order-by.g	                        (rev 0)
+++ core/patches/JBPAPP-6940/grammar/order-by.g	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,440 @@
+header
+{
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.sql.ordering.antlr;
+}
+/**
+ * Antlr grammar for dealing with <tt>order-by</tt> mapping fragments.
+
+ * @author Steve Ebersole
+ */
+class GeneratedOrderByFragmentParser extends Parser;
+
+options
+{
+	exportVocab=OrderByTemplate;
+	buildAST=true;
+	k=3;
+}
+
+tokens
+{
+    // synthetic tokens
+    ORDER_BY;
+    SORT_SPEC;
+    ORDER_SPEC;
+    SORT_KEY;
+    EXPR_LIST;
+    DOT;
+    IDENT_LIST;
+    COLUMN_REF;
+
+    COLLATE="collate";
+	ASCENDING="asc";
+	DESCENDING="desc";
+}
+
+
+{
+    /**
+     * Method for logging execution trace information.
+     *
+     * @param msg The trace message.
+     */
+    protected void trace(String msg) {
+        System.out.println( msg );
+    }
+
+    /**
+     * Extract a node's text.
+     *
+     * @param ast The node
+     *
+     * @return The text.
+     */
+    protected final String extractText(AST ast) {
+        // for some reason, within AST creation blocks "[]" I am somtimes unable to refer to the AST.getText() method
+        // using #var (the #var is not interpreted as the rule's output AST).
+        return ast.getText();
+    }
+
+    /**
+     * Process the given node as a quote identifier.  These need to be quoted in the dialect-specific way.
+     *
+     * @param ident The quoted-identifier node.
+     *
+     * @return The processed node.
+     *
+     * @see org.hibernate.dialect.Dialect#quote
+     */
+    protected AST quotedIdentifier(AST ident) {
+        return ident;
+    }
+
+    /**
+     * Process the given node as a quote string.
+     *
+     * @param ident The quoted string.  This is used from within function param recognition, and represents a
+     * SQL-quoted string.
+     *
+     * @return The processed node.
+     */
+    protected AST quotedString(AST ident) {
+        return ident;
+    }
+
+    /**
+     * A check to see if the text of the given node represents a known function name.
+     *
+     * @param ast The node whose text we want to check.
+     *
+     * @return True if the node's text is a known function name, false otherwise.
+     *
+     * @see org.hibernate.dialect.function.SQLFunctionRegistry
+     */
+    protected boolean isFunctionName(AST ast) {
+        return false;
+    }
+
+    /**
+     * Process the given node as a function.
+     *
+     * @param The node representing the function invocation (including parameters as subtree components).
+     *
+     * @return The processed node.
+     */
+    protected AST resolveFunction(AST ast) {
+        return ast;
+    }
+
+    /**
+     * Process the given node as an IDENT.  May represent either a column reference or a property reference.
+     *
+     * @param ident The node whose text represents either a column or property reference.
+     *
+     * @return The processed node.
+     */
+    protected AST resolveIdent(AST ident) {
+        return ident;
+    }
+
+    /**
+     * Allow post processing of each <tt>sort specification</tt>
+     *
+     * @param The grammar-built sort specification subtree.
+     *
+     * @return The processed sort specification subtree.
+     */
+    protected AST postProcessSortSpecification(AST sortSpec) {
+        return sortSpec;
+    }
+
+}
+
+/**
+ * Main recognition rule for this grammar
+ */
+orderByFragment { trace("orderByFragment"); }
+    : sortSpecification ( COMMA! sortSpecification  )* {
+        #orderByFragment = #( [ORDER_BY, "order-by"], #orderByFragment );
+    }
+    ;
+
+/**
+ * Recognition rule for what ANSI SQL terms the <tt>sort specification</tt>, which is essentially each thing upon which
+ * the results should be sorted.
+ */
+sortSpecification { trace("sortSpecification"); }
+    : sortKey (collationSpecification)? (orderingSpecification)? {
+        #sortSpecification = #( [SORT_SPEC, "{sort specification}"], #sortSpecification );
+        #sortSpecification = postProcessSortSpecification( #sortSpecification );
+    }
+    ;
+
+/**
+ * Recognition rule for what ANSI SQL terms the <tt>sort key</tt> which is the expression (column, function, etc) upon
+ * which to base the sorting.
+ */
+sortKey! { trace("sortKey"); }
+    : e:expression {
+        #sortKey = #( [SORT_KEY, "sort key"], #e );
+    }
+    ;
+
+/**
+ * Recognition rule what this grammar recognizes as valid <tt>sort key</tt>.
+ */
+expression! { trace("expression"); }
+    : HARD_QUOTE qi:IDENT HARD_QUOTE {
+        #expression = quotedIdentifier( #qi );
+    }
+    | ( IDENT (DOT IDENT)* OPEN_PAREN ) => f:functionCall {
+        #expression = #f;
+    }
+    | p:simplePropertyPath {
+        #expression = resolveIdent( #p );
+    }
+    | i:IDENT {
+        if ( isFunctionName( #i ) ) {
+            #expression = resolveFunction( #i );
+        }
+        else {
+            #expression = resolveIdent( #i );
+        }
+    }
+    ;
+
+/**
+ * Intended for use as a syntactic predicate to determine whether an IDENT represents a known SQL function name.
+ */
+functionCallCheck! { trace("functionCallCheck"); }
+    : IDENT (DOT IDENT)* OPEN_PAREN { true }?
+    ;
+
+/**
+ * Recognition rule for a function call
+ */
+functionCall! { trace("functionCall"); }
+    : fn:functionName OPEN_PAREN pl:functionParameterList CLOSE_PAREN {
+        #functionCall = #( [IDENT, extractText( #fn )], #pl );
+        #functionCall = resolveFunction( #functionCall );
+    }
+    ;
+
+/**
+ * A function-name is an IDENT followed by zero or more (DOT IDENT) sequences
+ */
+functionName {
+        trace("functionName");
+        StringBuilder buffer = new StringBuilder();
+    }
+    : i:IDENT { buffer.append( i.getText() ); }
+            ( DOT i2:IDENT { buffer.append( '.').append( i2.getText() ); } )* {
+        #functionName = #( [IDENT,buffer.toString()] );
+    }
+    ;
+
+/**
+ * Recognition rule used to "wrap" all function parameters into an EXPR_LIST node
+ */
+functionParameterList { trace("functionParameterList"); }
+    : functionParameter ( COMMA! functionParameter )* {
+        #functionParameterList = #( [EXPR_LIST, "{param list}"], #functionParameterList );
+    }
+    ;
+
+/**
+ * Recognized function parameters.
+ */
+functionParameter { trace("functionParameter"); }
+    : expression
+    | NUM_DOUBLE
+    | NUM_FLOAT
+    | NUM_INT
+    | NUM_LONG
+    | QUOTED_STRING {
+        #functionParameter = quotedString( #functionParameter );
+    }
+    ;
+
+/**
+ * Recognition rule for what ANSI SQL terms the <tt>collation specification</tt> used to allow specifying that sorting for
+ * the given {@link #sortSpecification} be treated within a specific character-set.
+ */
+collationSpecification! { trace("collationSpecification"); }
+    : c:COLLATE cn:collationName {
+        #collationSpecification = #( [COLLATE, extractText( #cn )] );
+    }
+    ;
+
+/**
+ * The collation name wrt {@link #collationSpecification}.  Namely, the character-set.
+ */
+collationName { trace("collationSpecification"); }
+    : IDENT
+    ;
+
+/**
+ * Recognition rule for what ANSI SQL terms the <tt>ordering specification</tt>; <tt>ASCENDING</tt> or
+ * <tt>DESCENDING</tt>.
+ */
+orderingSpecification! { trace("orderingSpecification"); }
+    : ( "asc" | "ascending" ) {
+        #orderingSpecification = #( [ORDER_SPEC, "asc"] );
+    }
+    | ( "desc" | "descending") {
+        #orderingSpecification = #( [ORDER_SPEC, "desc"] );
+    }
+    ;
+
+/**
+ * A simple-property-path is an IDENT followed by one or more (DOT IDENT) sequences
+ */
+simplePropertyPath {
+        trace("simplePropertyPath");
+        StringBuilder buffer = new StringBuilder();
+    }
+    : i:IDENT { buffer.append( i.getText() ); }
+            ( DOT i2:IDENT { buffer.append( '.').append( i2.getText() ); } )+ {
+        #simplePropertyPath = #( [IDENT,buffer.toString()] );
+    }
+    ;
+
+
+// **** LEXER ******************************************************************
+
+/**
+ * Lexer for the <tt>order-by</tt> fragment parser
+
+ * @author Steve Ebersole
+ * @author Joshua Davis
+ */
+class GeneratedOrderByLexer extends Lexer;
+
+options {
+	exportVocab=OrderByTemplate;
+	testLiterals = false;
+	k=2;
+	charVocabulary='\u0000'..'\uFFFE';	// Allow any char but \uFFFF (16 bit -1, ANTLR's EOF character)
+	caseSensitive = false;
+	caseSensitiveLiterals = false;
+}
+
+// -- Keywords --
+
+OPEN_PAREN: '(';
+CLOSE_PAREN: ')';
+
+COMMA: ',';
+
+HARD_QUOTE: '`';
+
+IDENT options { testLiterals=true; }
+	: ID_START_LETTER ( ID_LETTER )*
+	;
+
+protected
+ID_START_LETTER
+    :    '_'
+    |    '$'
+    |    'a'..'z'
+    |    '\u0080'..'\ufffe'       // HHH-558 : Allow unicode chars in identifiers
+    ;
+
+protected
+ID_LETTER
+    :    ID_START_LETTER
+    |    '0'..'9'
+    ;
+
+QUOTED_STRING
+	  : '\'' ( (ESCqs)=> ESCqs | ~'\'' )* '\''
+	;
+
+protected
+ESCqs
+	:
+		'\'' '\''
+	;
+
+//--- From the Java example grammar ---
+// a numeric literal
+NUM_INT
+	{boolean isDecimal=false; Token t=null;}
+	:   '.' {_ttype = DOT;}
+			(	('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})?
+				{
+					if (t != null && t.getText().toUpperCase().indexOf('F')>=0)
+					{
+						_ttype = NUM_FLOAT;
+					}
+					else
+					{
+						_ttype = NUM_DOUBLE; // assume double
+					}
+				}
+			)?
+	|	(	'0' {isDecimal = true;} // special case for just '0'
+			(	('x')
+				(											// hex
+					// the 'e'|'E' and float suffix stuff look
+					// like hex digits, hence the (...)+ doesn't
+					// know when to stop: ambig.  ANTLR resolves
+					// it correctly by matching immediately.  It
+					// is therefore ok to hush warning.
+					options { warnWhenFollowAmbig=false; }
+				:	HEX_DIGIT
+				)+
+			|	('0'..'7')+									// octal
+			)?
+		|	('1'..'9') ('0'..'9')*  {isDecimal=true;}		// non-zero decimal
+		)
+		(	('l') { _ttype = NUM_LONG; }
+
+		// only check to see if it's a float if looks like decimal so far
+		|	{isDecimal}?
+			(   '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})?
+			|   EXPONENT (f3:FLOAT_SUFFIX {t=f3;})?
+			|   f4:FLOAT_SUFFIX {t=f4;}
+			)
+			{
+				if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0)
+				{
+					_ttype = NUM_FLOAT;
+				}
+				else
+				{
+					_ttype = NUM_DOUBLE; // assume double
+				}
+			}
+		)?
+	;
+
+// hexadecimal digit (again, note it's protected!)
+protected
+HEX_DIGIT
+	:	('0'..'9'|'a'..'f')
+	;
+
+// a couple protected methods to assist in matching floating point numbers
+protected
+EXPONENT
+	:	('e') ('+'|'-')? ('0'..'9')+
+	;
+
+protected
+FLOAT_SUFFIX
+	:	'f'|'d'
+	;
+
+WS  :   (   ' '
+		|   '\t'
+		|   '\r' '\n' { newline(); }
+		|   '\n'      { newline(); }
+		|   '\r'      { newline(); }
+		)
+		{$setType(Token.SKIP);} //ignore this token
+	;

Modified: core/patches/JBPAPP-6940/src/org/hibernate/hql/ast/util/ASTPrinter.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/hql/ast/util/ASTPrinter.java	2012-08-30 16:52:35 UTC (rev 21064)
+++ core/patches/JBPAPP-6940/src/org/hibernate/hql/ast/util/ASTPrinter.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -149,7 +149,7 @@
 	 * @return String - The token type name from the token type constant class,
 	 *         or just the integer as a string if none exists.
 	 */
-	private String getTokenTypeName(int type) {
+	public String getTokenTypeName(int type) {
 		// If the class with the constants in it was not supplied, just
 		// use the integer token type as the token type name.
 		if ( tokenTypeConstants == null ) {

Modified: core/patches/JBPAPP-6940/src/org/hibernate/persister/collection/AbstractCollectionPersister.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/persister/collection/AbstractCollectionPersister.java	2012-08-30 16:52:35 UTC (rev 21064)
+++ core/patches/JBPAPP-6940/src/org/hibernate/persister/collection/AbstractCollectionPersister.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -18,8 +18,6 @@
 import org.hibernate.MappingException;
 import org.hibernate.QueryException;
 import org.hibernate.TransientObjectException;
-import org.hibernate.jdbc.Expectation;
-import org.hibernate.jdbc.Expectations;
 import org.hibernate.cache.CacheConcurrencyStrategy;
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.entry.CacheEntryStructure;
@@ -30,14 +28,16 @@
 import org.hibernate.collection.PersistentCollection;
 import org.hibernate.dialect.Dialect;
 import org.hibernate.engine.EntityKey;
+import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
 import org.hibernate.engine.PersistenceContext;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.engine.SessionImplementor;
 import org.hibernate.engine.SubselectFetch;
-import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
 import org.hibernate.exception.JDBCExceptionHelper;
 import org.hibernate.exception.SQLExceptionConverter;
 import org.hibernate.id.IdentifierGenerator;
+import org.hibernate.jdbc.Expectation;
+import org.hibernate.jdbc.Expectations;
 import org.hibernate.loader.collection.CollectionInitializer;
 import org.hibernate.mapping.Collection;
 import org.hibernate.mapping.Column;
@@ -51,11 +51,18 @@
 import org.hibernate.persister.entity.EntityPersister;
 import org.hibernate.persister.entity.Loadable;
 import org.hibernate.persister.entity.PropertyMapping;
+import org.hibernate.persister.entity.Queryable;
 import org.hibernate.pretty.MessageHelper;
 import org.hibernate.sql.Alias;
 import org.hibernate.sql.SelectFragment;
 import org.hibernate.sql.SimpleSelect;
 import org.hibernate.sql.Template;
+import org.hibernate.sql.ordering.antlr.ColumnMapper;
+import org.hibernate.sql.ordering.antlr.ColumnReference;
+import org.hibernate.sql.ordering.antlr.FormulaReference;
+import org.hibernate.sql.ordering.antlr.OrderByAliasResolver;
+import org.hibernate.sql.ordering.antlr.OrderByTranslation;
+import org.hibernate.sql.ordering.antlr.SqlValueReference;
 import org.hibernate.type.AbstractComponentType;
 import org.hibernate.type.CollectionType;
 import org.hibernate.type.EntityType;
@@ -89,14 +96,17 @@
 	private final String sqlDetectRowByIndexString;
 	private final String sqlDetectRowByElementString;
 
-	private final String sqlOrderByString;
 	protected final String sqlWhereString;
-	private final String sqlOrderByStringTemplate;
 	private final String sqlWhereStringTemplate;
-	private final boolean hasOrder;
 	protected final boolean hasWhere;
 	private final int baseIndex;
 	
+	private final boolean hasOrder;
+	private final OrderByTranslation orderByTranslation;
+	
+	private final boolean hasManyToManyOrder;
+	private final OrderByTranslation manyToManyOrderByTranslation;
+	
 	private final String nodeName;
 	private final String elementNodeName;
 	private final String indexNodeName;
@@ -173,9 +183,6 @@
 	private final String manyToManyWhereString;
 	private final String manyToManyWhereTemplate;
 
-	private final String manyToManyOrderByString;
-	private final String manyToManyOrderByTemplate;
-
 	// custom sql
 	private final boolean insertCallable;
 	private final boolean updateCallable;
@@ -243,12 +250,7 @@
 		for ( int i = 1; i < spacesSize; i++ ) {
 			spaces[i] = (String) iter.next();
 		}
-		
-		sqlOrderByString = collection.getOrderBy();
-		hasOrder = sqlOrderByString != null;
-		sqlOrderByStringTemplate = hasOrder ?
-				Template.renderOrderByStringTemplate(sqlOrderByString, dialect, factory.getSqlFunctionRegistry()) :
-				null;
+				
 		sqlWhereString = StringHelper.isNotEmpty( collection.getWhere() ) ? "( " + collection.getWhere() + ") " : null;
 		hasWhere = sqlWhereString != null;
 		sqlWhereStringTemplate = hasWhere ?
@@ -517,6 +519,20 @@
 					);
 			}
 		}
+		
+		hasOrder = collection.getOrderBy() != null;
+		if ( hasOrder ) {
+			orderByTranslation = Template.translateOrderBy(
+					collection.getOrderBy(),
+					new ColumnMapperImpl(),
+					factory,
+					dialect,
+					factory.getSqlFunctionRegistry()
+					);
+		}
+		else {
+			orderByTranslation = null;
+		}
 			
 		// Handle any filters applied to this collection
 		filterHelper = new FilterHelper( collection.getFilterMap(), dialect, factory.getSqlFunctionRegistry() );
@@ -529,14 +545,76 @@
 		manyToManyWhereTemplate = manyToManyWhereString == null ?
 				null :
 				Template.renderWhereStringTemplate( manyToManyWhereString, factory.getDialect(), factory.getSqlFunctionRegistry() );
-		manyToManyOrderByString = collection.getManyToManyOrdering();
-		manyToManyOrderByTemplate = manyToManyOrderByString == null
-				? null
-	            : Template.renderOrderByStringTemplate( manyToManyOrderByString, factory.getDialect(), factory.getSqlFunctionRegistry() );
+		
+		hasManyToManyOrder = collection.getManyToManyOrdering() != null;
+		if ( hasManyToManyOrder ) {
+			manyToManyOrderByTranslation = Template.translateOrderBy(
+					collection.getManyToManyOrdering(),
+					new ColumnMapperImpl(),
+					factory,
+					dialect,
+					factory.getSqlFunctionRegistry()
+					);
+		}
+		else {
+			manyToManyOrderByTranslation = null;
+		}
 
 		initCollectionPropertyMap();
 	}
+	
+	private class ColumnMapperImpl implements ColumnMapper {
+		public SqlValueReference[] map(String reference) {
+			final String[] columnNames;
+			final String[] formulaTemplates;
 
+			// handle the special "$element$" property name...
+			if ( "$element$".equals( reference ) ) {
+				columnNames = elementColumnNames;
+				formulaTemplates = elementFormulaTemplates;
+			}
+			else {
+				columnNames = elementPropertyMapping.toColumns( reference );
+				formulaTemplates = formulaTemplates( reference, columnNames.length );
+			}
+
+			final SqlValueReference[] result = new SqlValueReference[ columnNames.length ];
+			int i = 0;
+			for ( final String columnName : columnNames ) {
+				if ( columnName == null ) {
+					// if the column name is null, it indicates that this index in the property value mapping is
+					// actually represented by a formula.
+					final int propertyIndex = elementPersister.getEntityMetamodel().getPropertyIndex( reference );
+					final String formulaTemplate = formulaTemplates[i];
+					result[i] = new FormulaReference() {
+						public String getFormulaFragment() {
+							return formulaTemplate;
+						}
+					};
+				}
+				else {
+					result[i] = new ColumnReference() {
+						public String getColumnName() {
+							return columnName;
+						}
+					};
+				}
+				i++;
+			}
+			return result;
+		}
+	}
+
+	private String[] formulaTemplates(String reference, int expectedSize) {
+		try {
+			final int propertyIndex = elementPersister.getEntityMetamodel().getPropertyIndex( reference );
+			return  ( (Queryable) elementPersister ).getSubclassPropertyFormulaTemplateClosure()[propertyIndex];
+		}
+		catch (Exception e) {
+			return new String[expectedSize];
+		}
+	}
+
 	public void postInstantiate() throws MappingException {
 		initializer = queryLoaderName == null ?
 				createCollectionInitializer( CollectionHelper.EMPTY_MAP ) :
@@ -635,18 +713,17 @@
 	}
 
 	public String getSQLOrderByString(String alias) {
-		return hasOrdering() ? 
-			StringHelper.replace( sqlOrderByStringTemplate, Template.TEMPLATE, alias ) : "";
+		return hasOrdering()
+				? orderByTranslation.injectAliases( new StandardOrderByAliasResolver( alias ) )
+						: "";
 	}
 
 	public String getManyToManyOrderByString(String alias) {
-		if ( isManyToMany() && manyToManyOrderByString != null ) {
-			return StringHelper.replace( manyToManyOrderByTemplate, Template.TEMPLATE, alias );
-		}
-		else {
-			return "";
-		}
+		return hasManyToManyOrdering()
+				? manyToManyOrderByTranslation.injectAliases( new StandardOrderByAliasResolver( alias ) )
+						: "";
 	}
+	
 	public FetchMode getFetchMode() {
 		return fetchMode;
 	}
@@ -656,7 +733,7 @@
 	}
 
 	public boolean hasManyToManyOrdering() {
-		return isManyToMany() && manyToManyOrderByTemplate != null;
+		return isManyToMany() && hasManyToManyOrder;
 	}
 
 	public boolean hasWhere() {
@@ -1792,4 +1869,22 @@
 	public CollectionInitializer getInitializer() {
 		return initializer;
 	}
+	
+	private class StandardOrderByAliasResolver implements OrderByAliasResolver {
+		private final String rootAlias;
+
+		private StandardOrderByAliasResolver(String rootAlias) {
+			this.rootAlias = rootAlias;
+		}
+
+		public String resolveTableAlias(String columnReference) {
+			if ( elementPersister == null ) {
+				// we have collection of non-entity elements...
+				return rootAlias;
+			}
+			else {
+				return ( (Loadable) elementPersister ).getTableAliasForColumn( columnReference, rootAlias );
+			}
+		}
+	}
 }

Modified: core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/AbstractEntityPersister.java	2012-08-30 16:52:35 UTC (rev 21064)
+++ core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/AbstractEntityPersister.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -1488,7 +1488,7 @@
 		return propertyDefinedOnSubclass[i];
 	}
 
-	protected String[][] getSubclassPropertyFormulaTemplateClosure() {
+	public String[][] getSubclassPropertyFormulaTemplateClosure() {
 		return subclassPropertyFormulaTemplateClosure;
 	}
 
@@ -3844,6 +3844,13 @@
 			throws HibernateException {
 		getTuplizer( entityMode ).setPropertyValue( object, propertyName, value );
 	}
-	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+	
+	public String getTableAliasForColumn(String columnName, String rootAlias) {
+		return generateTableAlias( rootAlias, determineTableNumberForColumn( columnName ) );
+	}
 
+	public int determineTableNumberForColumn(String columnName) {
+		return 0;
+	}
+
 }

Modified: core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java	2012-08-30 16:52:35 UTC (rev 21064)
+++ core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -584,4 +584,24 @@
 		}
 		return super.getSubclassPropertyDeclarer( propertyPath );
 	}
+	
+	@Override
+	public int determineTableNumberForColumn(String columnName) {
+		final String[] subclassColumnNameClosure = getSubclassColumnClosure();
+		for ( int i = 0, max = subclassColumnNameClosure.length; i < max; i++ ) {
+			final boolean quoted = subclassColumnNameClosure[i].startsWith( "\"" )
+					&& subclassColumnNameClosure[i].endsWith( "\"" );
+			if ( quoted ) {
+				if ( subclassColumnNameClosure[i].equals( columnName ) ) {
+					return getSubclassColumnTableNumberClosure()[i];
+				}
+			}
+			else {
+				if ( subclassColumnNameClosure[i].equalsIgnoreCase( columnName ) ) {
+					return getSubclassColumnTableNumberClosure()[i];
+				}
+			}
+		}
+		throw new HibernateException( "Could not locate table which owns column [" + columnName + "] referenced in order-by mapping" );
+	}
 }

Modified: core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/Loadable.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/Loadable.java	2012-08-30 16:52:35 UTC (rev 21064)
+++ core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/Loadable.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -85,4 +85,18 @@
 
 	public boolean isAbstract();
 
+	/**
+	 * Given a column name and the root table alias in use for the entity hierarchy, determine the proper table alias
+	 * for the table in that hierarchy that contains said column.
+	 * <p/>
+	 * NOTE : Generally speaking the column is not validated to exist.  Most implementations simply return the
+	 * root alias; the exception is {@link JoinedSubclassEntityPersister}
+	 *
+	 * @param columnName The column name
+	 * @param rootAlias The hierarchy root alias
+	 *
+	 * @return The proper table alias for qualifying the given column.
+	 */
+	public String getTableAliasForColumn(String columnName, String rootAlias);
+
 }

Modified: core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/Queryable.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/Queryable.java	2012-08-30 16:52:35 UTC (rev 21064)
+++ core/patches/JBPAPP-6940/src/org/hibernate/persister/entity/Queryable.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -139,6 +139,8 @@
 	 */
 	public String generateFilterConditionAlias(String rootAlias);
 
+	String[][] getSubclassPropertyFormulaTemplateClosure();
+
 	public static class Declarer {
 		public static final Declarer CLASS = new Declarer( "class" );
 		public static final Declarer SUBCLASS = new Declarer( "subclass" );

Modified: core/patches/JBPAPP-6940/src/org/hibernate/sql/Template.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/Template.java	2012-08-30 16:52:35 UTC (rev 21064)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/Template.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -6,6 +6,13 @@
 
 import org.hibernate.dialect.Dialect;
 import org.hibernate.dialect.function.SQLFunctionRegistry;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.sql.ordering.antlr.ColumnMapper;
+import org.hibernate.sql.ordering.antlr.OrderByAliasResolver;
+import org.hibernate.sql.ordering.antlr.OrderByFragmentTranslator;
+import org.hibernate.sql.ordering.antlr.OrderByTranslation;
+import org.hibernate.sql.ordering.antlr.SqlValueReference;
+import org.hibernate.sql.ordering.antlr.TranslationContext;
 import org.hibernate.util.StringHelper;
 
 /**
@@ -208,93 +215,105 @@
 		return result.toString();
 	}
 
+
+
+	public static class NoOpColumnMapper implements ColumnMapper {
+		public static final NoOpColumnMapper INSTANCE = new NoOpColumnMapper();
+		public SqlValueReference[] map(String reference) {
+			// return new String[] { reference };
+			return null;
+		}
+	}
+
 	/**
-	 * Takes order by clause provided in the mapping attribute and interpolates the alias.
-	 * Handles asc, desc, SQL functions, quoted identifiers.
+	 * Performs order-by template rendering without {@link ColumnMapper column mapping}. An <tt>ORDER BY</tt> template
+	 * has all column references "qualified" with a placeholder identified by {@link Template#TEMPLATE}
+	 *
+	 * @param orderByFragment The order-by fragment to render.
+	 * @param dialect The SQL dialect being used.
+	 * @param functionRegistry The SQL function registry
+	 *
+	 * @return The rendered <tt>ORDER BY</tt> template.
+	 *
+	 * @deprecated Use {@link #translateOrderBy} instead
 	 */
-	public static String renderOrderByStringTemplate(String sqlOrderByString, Dialect dialect, SQLFunctionRegistry functionRegistry) {
-		//TODO: make this a bit nicer
-		String symbols = new StringBuffer()
-			.append("=><!+-*/()',|&`")
-			.append(StringHelper.WHITESPACE)
-			.append( dialect.openQuote() )
-			.append( dialect.closeQuote() )
-			.toString();
-		StringTokenizer tokens = new StringTokenizer(sqlOrderByString, symbols, true);
-		
-		StringBuffer result = new StringBuffer();
-		boolean quoted = false;
-		boolean quotedIdentifier = false;
-		
-		boolean hasMore = tokens.hasMoreTokens();
-		String nextToken = hasMore ? tokens.nextToken() : null;
-		while (hasMore) {
-			String token = nextToken;
-			String lcToken = token.toLowerCase();
-			hasMore = tokens.hasMoreTokens();
-			nextToken = hasMore ? tokens.nextToken() : null;
-			
-			boolean isQuoteCharacter = false;
-			
-			if ( !quotedIdentifier && "'".equals(token) ) {
-				quoted = !quoted;
-				isQuoteCharacter = true;
+	@Deprecated
+	public static String renderOrderByStringTemplate(
+			String orderByFragment,
+			Dialect dialect,
+			SQLFunctionRegistry functionRegistry) {
+		return renderOrderByStringTemplate(
+				orderByFragment,
+				NoOpColumnMapper.INSTANCE,
+				null,
+				dialect,
+				functionRegistry
+				);
+	}
+
+	public static String renderOrderByStringTemplate(
+			String orderByFragment,
+			final ColumnMapper columnMapper,
+			final SessionFactoryImplementor sessionFactory,
+			final Dialect dialect,
+			final SQLFunctionRegistry functionRegistry) {
+		return translateOrderBy(
+				orderByFragment,
+				columnMapper,
+				sessionFactory,
+				dialect,
+				functionRegistry
+				).injectAliases( LEGACY_ORDER_BY_ALIAS_RESOLVER );
+	}
+
+	public static OrderByAliasResolver LEGACY_ORDER_BY_ALIAS_RESOLVER = new OrderByAliasResolver() {
+		public String resolveTableAlias(String columnReference) {
+			return TEMPLATE;
+		}
+	};
+
+	/**
+	 * Performs order-by template rendering allowing {@link ColumnMapper column mapping}. An <tt>ORDER BY</tt> template
+	 * has all column references "qualified" with a placeholder identified by {@link Template#TEMPLATE} which can later
+	 * be used to easily inject the SQL alias.
+	 *
+	 * @param orderByFragment The order-by fragment to render.
+	 * @param columnMapper The column mapping strategy to use.
+	 * @param sessionFactory The session factory.
+	 * @param dialect The SQL dialect being used.
+	 * @param functionRegistry The SQL function registry
+	 *
+	 * @return The rendered <tt>ORDER BY</tt> template.
+	 */
+	public static OrderByTranslation translateOrderBy(
+			String orderByFragment,
+			final ColumnMapper columnMapper,
+			final SessionFactoryImplementor sessionFactory,
+			final Dialect dialect,
+			final SQLFunctionRegistry functionRegistry) {
+		TranslationContext context = new TranslationContext() {
+			public SessionFactoryImplementor getSessionFactory() {
+				return sessionFactory;
 			}
-			
-			if ( !quoted ) {
-				
-				boolean isOpenQuote;
-				if ( "`".equals(token) ) {
-					isOpenQuote = !quotedIdentifier;
-					token = lcToken = isOpenQuote ? 
-						new Character( dialect.openQuote() ).toString() :
-						new Character( dialect.closeQuote() ).toString();
-					quotedIdentifier = isOpenQuote;	
-					isQuoteCharacter = true;
-				}
-				else if ( !quotedIdentifier && ( dialect.openQuote()==token.charAt(0) ) ) {
-					isOpenQuote = true;
-					quotedIdentifier = true;	
-					isQuoteCharacter = true;
-				}
-				else if ( quotedIdentifier && ( dialect.closeQuote()==token.charAt(0) ) ) {
-					quotedIdentifier = false;
-					isQuoteCharacter = true;
-					isOpenQuote = false;
-				}
-				else {
-					isOpenQuote = false;
-				}
-				
-				if (isOpenQuote) {
-					result.append(TEMPLATE).append('.');
-				}
-				
+
+			public Dialect getDialect() {
+				return dialect;
 			}
-	
-			boolean quotedOrWhitespace = quoted || 
-				quotedIdentifier || 
-				isQuoteCharacter || 
-				Character.isWhitespace( token.charAt(0) );
-			
-			if (quotedOrWhitespace) {
-				result.append(token);
+
+			public SQLFunctionRegistry getSqlFunctionRegistry() {
+				return functionRegistry;
 			}
-			else if (
-				isIdentifier(token, dialect) &&
-				!isFunctionOrKeyword(lcToken, nextToken, dialect, functionRegistry)
-			) {
-				result.append(TEMPLATE)
-					.append('.')
-					.append( dialect.quote(token) );
+
+			public ColumnMapper getColumnMapper() {
+				return columnMapper;
 			}
-			else {
-				result.append(token);
-			}
-		}
-		return result.toString();
+		};
+
+		return OrderByFragmentTranslator.translate( context, orderByFragment );
 	}
+
 	
+	
 	private static boolean isNamedParameter(String token) {
 		return token.startsWith(":");
 	}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/CollationSpecification.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/CollationSpecification.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/CollationSpecification.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,33 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+/**
+ * Models a collation specification (<tt>COLLATE</tt> using a specific character-set) within a
+ * {@link SortSpecification}.
+ *
+ * @author Steve Ebersole
+ */
+public class CollationSpecification extends NodeSupport {
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/ColumnMapper.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/ColumnMapper.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/ColumnMapper.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,46 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+import org.hibernate.HibernateException;
+
+/**
+ * Contract for mapping a (an assumed) property reference to its columns.
+ *
+ * @author Steve Ebersole
+ */
+public interface ColumnMapper {
+	/**
+	 * Resolve the property reference to its underlying columns.
+	 *
+	 * @param reference The property reference name.
+	 *
+	 * @return References to the columns/formulas that define the value mapping for the given property, or null
+	 * if the property reference is unknown.
+	 *
+	 * @throws HibernateException Generally indicates that the property reference is unknown; interpretation
+	 * should be the same as a null return.
+	 */
+	public SqlValueReference[] map(String reference) throws HibernateException;
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/ColumnReference.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/ColumnReference.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/ColumnReference.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,38 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+/**
+ * Reference to a column name.
+ *
+ * @author Steve Ebersole
+ */
+public interface ColumnReference extends SqlValueReference {
+	/**
+	 * Retrieve the column name.
+	 *
+	 * @return THe column name
+	 */
+	public String getColumnName();
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/Factory.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/Factory.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/Factory.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,51 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+import antlr.ASTFactory;
+
+/**
+ * Acts as a {@link ASTFactory} for injecting our specific AST node classes into the Antlr generated trees.
+ *
+ * @author Steve Ebersole
+ */
+public class Factory extends ASTFactory implements OrderByTemplateTokenTypes {
+	@Override
+	public Class getASTNodeType(int i) {
+		switch ( i ) {
+			case ORDER_BY:
+				return OrderByFragment.class;
+			case SORT_SPEC:
+				return SortSpecification.class;
+			case ORDER_SPEC:
+				return OrderingSpecification.class;
+			case COLLATE:
+				return CollationSpecification.class;
+			case SORT_KEY:
+				return SortKey.class;
+			default:
+				return NodeSupport.class;
+		}
+	}
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/FormulaReference.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/FormulaReference.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/FormulaReference.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,40 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+/**
+ * Reference to a formula fragment.
+ *
+ * @author Steve Ebersole
+ */
+public interface FormulaReference extends SqlValueReference {
+	/**
+	 * Retrieve the formula fragment.  It is important to note that this is what the persister calls the
+	 * "formula template", which has the $PlaceHolder$ (see {@link org.hibernate.sql.Template#TEMPLATE})
+	 * markers injected.
+	 *
+	 * @return The formula fragment template.
+	 */
+	public String getFormulaFragment();
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/Node.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/Node.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/Node.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,52 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+/**
+ * General contract for AST nodes.
+ *
+ * @author Steve Ebersole
+ */
+public interface Node {
+	/**
+	 * Get the intrinsic text of this node.
+	 *
+	 * @return The node's text.
+	 */
+	public String getText();
+
+	/**
+	 * Get a string representation of this node usable for debug logging or similar.
+	 *
+	 * @return The node's debugging text.
+	 */
+	public String getDebugText();
+
+	/**
+	 * Build the node's representation for use in the resulting rendering.
+	 *
+	 * @return The text for use in the translated output.
+	 */
+	public String getRenderableText();
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/NodeSupport.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/NodeSupport.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/NodeSupport.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,41 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+import antlr.CommonAST;
+
+/**
+ * Basic implementation of a {@link Node} briding to the Antlr {@link CommonAST} hierarchy.
+ *
+ * @author Steve Ebersole
+ */
+public class NodeSupport extends CommonAST implements Node {
+	public String getDebugText() {
+		return getText();
+	}
+
+	public String getRenderableText() {
+		return getText();
+	}
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByAliasResolver.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByAliasResolver.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByAliasResolver.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,35 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+/**
+ * Given a column reference, resolve the table alias to apply to the column to qualify it.
+ */
+public interface OrderByAliasResolver {
+	/**
+	 * Given a column reference, resolve the table alias to apply to the column to qualify it.
+	 *
+	 */
+	public String resolveTableAlias(String columnReference);
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragment.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragment.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragment.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,32 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+/**
+ * Represents a parsed <tt>order-by</tt> mapping fragment.  This holds the tree of all {@link SortSpecification}s.
+ *
+ * @author Steve Ebersole
+ */
+public class OrderByFragment extends NodeSupport {
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentParser.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentParser.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentParser.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,333 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.hibernate.dialect.function.SQLFunction;
+import org.hibernate.sql.Template;
+import org.hibernate.util.StringHelper;
+import org.jboss.logging.Logger;
+
+import antlr.CommonAST;
+import antlr.TokenStream;
+import antlr.collections.AST;
+
+/**
+ * Extension of the Antlr-generated parser for the purpose of adding our custom parsing behavior
+ * (semantic analysis, etc).
+ *
+ * @author Steve Ebersole
+ */
+public class OrderByFragmentParser extends GeneratedOrderByFragmentParser {
+    private static final Logger LOG = Logger.getLogger(OrderByFragmentParser.class.getName());
+
+	private final TranslationContext context;
+
+	private Set<String> columnReferences = new HashSet<String>();
+
+	public OrderByFragmentParser(TokenStream lexer, TranslationContext context) {
+		super( lexer );
+		super.setASTFactory( new Factory() );
+		this.context = context;
+	}
+
+	public Set<String> getColumnReferences() {
+		return columnReferences;
+	}
+
+	@Override
+    protected AST quotedIdentifier(AST ident) {
+		/*
+		 * Semantic action used during recognition of quoted identifiers (quoted column names)
+		 */
+		final String columnName = context.getDialect().quote( '`' + ident.getText() + '`' );
+		columnReferences.add( columnName );
+		final String marker = '{' + columnName + '}';
+		return getASTFactory().create( OrderByTemplateTokenTypes.IDENT, marker );
+	}
+
+	@Override
+    protected AST quotedString(AST ident) {
+		/*
+		 * Semantic action used during recognition of quoted strings (string literals)
+		 */
+		return getASTFactory().create( OrderByTemplateTokenTypes.IDENT, context.getDialect().quote( ident.getText() ) );
+	}
+
+	@Override
+	@SuppressWarnings("SimplifiableIfStatement")
+	protected boolean isFunctionName(AST ast) {
+		/*
+		 * Semantic predicate used to determine whether a given AST node represents a function call
+		 */
+
+		AST child = ast.getFirstChild();
+		// assume it is a function if it has parameters
+		if ( child != null && "{param list}".equals( child.getText() ) ) {
+			return true;
+		}
+
+		// otherwise, in order for this to be a function logically it has to be a function that does not
+		// have arguments.  So try to assert that using the registry of known functions
+		final SQLFunction function = context.getSqlFunctionRegistry().findSQLFunction( ast.getText() );
+		if ( function == null ) {
+			// no registered function, so we cannot know for certain
+			return false;
+		}
+		else {
+			// if function.hasParenthesesIfNoArguments() is true, then assume the node is not a function
+			return ! function.hasParenthesesIfNoArguments();
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+    protected AST resolveFunction(AST ast) {
+		/*
+		 * Semantic action used during recognition of a *known* function
+		 */
+		AST child = ast.getFirstChild();
+		if ( child != null ) {
+			assert "{param list}".equals(  child.getText() );
+			child = child.getFirstChild();
+		}
+
+		final String functionName = ast.getText();
+		final SQLFunction function = context.getSqlFunctionRegistry().findSQLFunction( functionName );
+		if ( function == null ) {
+			String text = functionName;
+			if ( child != null ) {
+				text += '(';
+				while ( child != null ) {
+					text += resolveFunctionArgument( child );
+					child = child.getNextSibling();
+					if ( child != null ) {
+						text += ", ";
+					}
+				}
+				text += ')';
+			}
+			return getASTFactory().create( OrderByTemplateTokenTypes.IDENT, text );
+		}
+		else {
+			ArrayList expressions = new ArrayList();
+			while ( child != null ) {
+				expressions.add( resolveFunctionArgument( child ) );
+				child = child.getNextSibling();
+			}
+			final String text = function.render( expressions, context.getSessionFactory() );
+			return getASTFactory().create( OrderByTemplateTokenTypes.IDENT, text );
+		}
+	}
+
+	private String resolveFunctionArgument(AST argumentNode) {
+		final String nodeText = argumentNode.getText();
+		final String adjustedText;
+		if ( nodeText.contains( Template.TEMPLATE ) ) {
+			// we have a SQL order-by fragment
+			adjustedText = adjustTemplateReferences( nodeText );
+		}
+		else if ( nodeText.startsWith( "{" ) && nodeText.endsWith( "}" ) ) {
+			columnReferences.add( nodeText.substring( 1, nodeText.length() - 1 ) );
+			return nodeText;
+		}
+		else {
+			adjustedText = nodeText;
+			// because we did not process the node text, we need to attempt to find any column references
+			// contained in it.
+			// NOTE : uses regex for the time being; we should check the performance of this
+			Pattern pattern = Pattern.compile( "\\{(.*)\\}" );
+			Matcher matcher = pattern.matcher( adjustedText );
+			while ( matcher.find() ) {
+				columnReferences.add( matcher.group( 1 ) );
+			}
+		}
+		return adjustedText;
+	}
+
+	@Override
+    protected AST resolveIdent(AST ident) {
+		/*
+		 * Semantic action used during recognition of an identifier.  This identifier might be a column name, it might
+		 * be a property name.
+		 */
+		String text = ident.getText();
+		SqlValueReference[] sqlValueReferences;
+		try {
+			sqlValueReferences = context.getColumnMapper().map( text );
+		}
+		catch( Throwable t ) {
+			sqlValueReferences = null;
+		}
+
+		if ( sqlValueReferences == null || sqlValueReferences.length == 0 ) {
+			return getASTFactory().create( OrderByTemplateTokenTypes.IDENT, makeColumnReference( text ) );
+		}
+		else if ( sqlValueReferences.length == 1 ) {
+			return processSqlValueReference( sqlValueReferences[0] );
+		}
+		else {
+			final AST root = getASTFactory().create( OrderByTemplateTokenTypes.IDENT_LIST, "{ident list}" );
+			for ( SqlValueReference sqlValueReference : sqlValueReferences ) {
+				root.addChild( processSqlValueReference( sqlValueReference ) );
+			}
+			return root;
+		}
+	}
+
+	private AST processSqlValueReference(SqlValueReference sqlValueReference) {
+		if ( ColumnReference.class.isInstance( sqlValueReference ) ) {
+			final String columnName = ( (ColumnReference) sqlValueReference ).getColumnName();
+			return getASTFactory().create( OrderByTemplateTokenTypes.IDENT, makeColumnReference( columnName ) );
+		}
+		else {
+			final String formulaFragment = ( (FormulaReference) sqlValueReference ).getFormulaFragment();
+			// formulas have already been "adjusted" for aliases by appending Template.TEMPLATE to places
+			// where we believe column references are.  Fixing that is beyond scope of this work.  But we need
+			// to re-adjust that to use the order-by expectation of wrapping the column names in curly
+			// braces (i.e., `{column_name}`).
+			final String adjustedText = adjustTemplateReferences( formulaFragment );
+			return getASTFactory().create( OrderByTemplateTokenTypes.IDENT, adjustedText );
+		}
+	}
+
+	private String makeColumnReference(String text) {
+		columnReferences.add( text );
+		return "{" + text + "}";
+	}
+
+	private static final int TEMPLATE_MARKER_LENGTH = Template.TEMPLATE.length();
+
+	private String adjustTemplateReferences(String template) {
+		int templateLength = template.length();
+		int startPos = template.indexOf( Template.TEMPLATE );
+		while ( startPos < templateLength ) {
+			int dotPos = startPos + TEMPLATE_MARKER_LENGTH;
+
+			// from here we need to seek the end of the qualified identifier
+			int pos = dotPos + 1;
+			while ( pos < templateLength && isValidIdentifierCharacter( template.charAt( pos ) ) ) {
+				pos++;
+			}
+
+			// At this point we know all 3 points in the template that are needed for replacement.
+			// Basically we will be replacing the whole match with the bit following the dot, but will wrap
+			// the replacement in curly braces.
+			final String columnReference = template.substring( dotPos + 1, pos );
+			final String replacement = "{" + columnReference + "}";
+			template = template.replace( template.substring( startPos, pos ), replacement );
+			columnReferences.add( columnReference );
+
+			// prep for the next seek
+			startPos = ( pos - TEMPLATE_MARKER_LENGTH ) + 1;
+			templateLength = template.length();
+		}
+
+		return template;
+	}
+
+	private static boolean isValidIdentifierCharacter(char c) {
+		return Character.isLetter( c )
+				|| Character.isDigit( c )
+				|| '_' == c
+				|| '\"' == c;
+	}
+
+	@Override
+    protected AST postProcessSortSpecification(AST sortSpec) {
+		assert SORT_SPEC == sortSpec.getType();
+		SortSpecification sortSpecification = ( SortSpecification ) sortSpec;
+		AST sortKey = sortSpecification.getSortKey();
+		if ( IDENT_LIST == sortKey.getFirstChild().getType() ) {
+			AST identList = sortKey.getFirstChild();
+			AST ident = identList.getFirstChild();
+			AST holder = new CommonAST();
+			do {
+				holder.addChild(
+						createSortSpecification(
+								ident,
+								sortSpecification.getCollation(),
+								sortSpecification.getOrdering()
+						)
+				);
+				ident = ident.getNextSibling();
+			} while ( ident != null );
+			sortSpec = holder.getFirstChild();
+		}
+		return sortSpec;
+	}
+
+	private SortSpecification createSortSpecification(
+			AST ident,
+			CollationSpecification collationSpecification,
+			OrderingSpecification orderingSpecification) {
+		AST sortSpecification = getASTFactory().create( SORT_SPEC, "{{sort specification}}" );
+		AST sortKey = getASTFactory().create( SORT_KEY, "{{sort key}}" );
+		AST newIdent = getASTFactory().create( ident.getType(), ident.getText() );
+		sortKey.setFirstChild( newIdent );
+		sortSpecification.setFirstChild( sortKey );
+		if ( collationSpecification != null ) {
+			sortSpecification.addChild( collationSpecification );
+		}
+		if ( orderingSpecification != null ) {
+			sortSpecification.addChild( orderingSpecification );
+		}
+		return ( SortSpecification ) sortSpecification;
+	}
+
+
+
+	// trace logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	private int traceDepth = 0;
+
+
+	@Override
+	public void traceIn(String ruleName) {
+		if ( inputState.guessing > 0 ) {
+			return;
+		}
+		String prefix = StringHelper.repeat( '-', (traceDepth++ * 2) ) + "-> ";
+		LOG.trace(prefix + ruleName);
+	}
+
+	@Override
+	public void traceOut(String ruleName) {
+		if ( inputState.guessing > 0 ) {
+			return;
+		}
+		String prefix = "<-" + StringHelper.repeat( '-', (--traceDepth * 2) ) + " ";
+		LOG.trace(prefix + ruleName);
+	}
+
+	@Override
+	protected void trace(String msg) {
+		LOG.trace( msg );
+	}
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentRenderer.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentRenderer.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentRenderer.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,78 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+import org.hibernate.hql.ast.util.ASTPrinter;
+import org.hibernate.util.StringHelper;
+import org.jboss.logging.Logger;
+
+import antlr.collections.AST;
+
+/**
+ * Extension of the Antlr-generated tree walker for rendering the parsed order-by tree back to String form.
+ * {@link #out(antlr.collections.AST)} is the sole semantic action here and it is used to utilize our
+ * split between text (tree debugging text) and "renderable text" (text to use during rendering).
+ *
+ * @author Steve Ebersole
+ */
+public class OrderByFragmentRenderer extends GeneratedOrderByFragmentRenderer {
+
+	private static final Logger LOG = Logger.getLogger( OrderByFragmentRenderer.class.getName() );
+	private static final ASTPrinter printer = new ASTPrinter( GeneratedOrderByFragmentRendererTokenTypes.class );
+
+	@Override
+    protected void out(AST ast) {
+		out( ( ( Node ) ast ).getRenderableText() );
+	}
+
+
+	// handle trace logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    private int traceDepth = 0;
+
+	@Override
+    public void traceIn(String ruleName, AST tree) {
+		if ( inputState.guessing > 0 ) {
+			return;
+		}
+		String prefix = StringHelper.repeat( '-', (traceDepth++ * 2) ) + "-> ";
+		String traceText = ruleName + " (" + buildTraceNodeName(tree) + ")";
+		LOG.trace( prefix + traceText );
+	}
+
+	private String buildTraceNodeName(AST tree) {
+		return tree == null
+				? "???"
+				: tree.getText() + " [" + printer.getTokenTypeName( tree.getType() ) + "]";
+	}
+
+	@Override
+    public void traceOut(String ruleName, AST tree) {
+		if ( inputState.guessing > 0 ) {
+			return;
+		}
+		String prefix = "<-" + StringHelper.repeat( '-', (--traceDepth * 2) ) + " ";
+		LOG.trace( prefix + ruleName );
+	}
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentTranslator.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentTranslator.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByFragmentTranslator.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,112 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+import java.io.StringReader;
+import java.util.Set;
+
+import org.hibernate.HibernateException;
+import org.hibernate.hql.ast.util.ASTPrinter;
+import org.jboss.logging.Logger;
+
+/**
+ * A translator for order-by mappings, whether specified by hbm.xml files, Hibernate
+ * {@link org.hibernate.annotations.OrderBy} annotation or JPA {@link javax.persistence.OrderBy} annotation.
+ *
+ * @author Steve Ebersole
+ */
+public class OrderByFragmentTranslator {
+	private static final Logger LOG = Logger.getLogger( OrderByFragmentTranslator.class.getName() );
+
+	/**
+	 * Perform the translation of the user-supplied fragment, returning the translation.
+	 * <p/>
+	 * The important distinction to this split between (1) translating and (2) resolving aliases is that
+	 * both happen at different times
+	 *
+	 *
+	 * @param context Context giving access to delegates needed during translation.
+	 * @param fragment The user-supplied order-by fragment
+	 *
+	 * @return The translation.
+	 */
+	public static OrderByTranslation translate(TranslationContext context, String fragment) {
+		GeneratedOrderByLexer lexer = new GeneratedOrderByLexer( new StringReader( fragment ) );
+
+		// Perform the parsing (and some analysis/resolution).  Another important aspect is the collection
+		// of "column references" which are important later to seek out replacement points in the
+		// translated fragment.
+		OrderByFragmentParser parser = new OrderByFragmentParser( lexer, context );
+		try {
+			parser.orderByFragment();
+		}
+		catch ( HibernateException e ) {
+			throw e;
+		}
+		catch ( Throwable t ) {
+			throw new HibernateException( "Unable to parse order-by fragment", t );
+		}
+
+		if ( LOG.isTraceEnabled() ) {
+			ASTPrinter printer = new ASTPrinter( OrderByTemplateTokenTypes.class );
+			LOG.trace( printer.showAsString( parser.getAST(), "--- {order-by fragment} ---" ) );
+		}
+
+		// Render the parsed tree to text.
+		OrderByFragmentRenderer renderer = new OrderByFragmentRenderer();
+		try {
+			renderer.orderByFragment( parser.getAST() );
+		}
+		catch ( HibernateException e ) {
+			throw e;
+		}
+		catch ( Throwable t ) {
+			throw new HibernateException( "Unable to render parsed order-by fragment", t );
+		}
+
+		return new StandardOrderByTranslationImpl( renderer.getRenderedFragment(), parser.getColumnReferences() );
+	}
+
+	public static class StandardOrderByTranslationImpl implements OrderByTranslation {
+		private final String sqlTemplate;
+		private final Set<String> columnReferences;
+
+		public StandardOrderByTranslationImpl(String sqlTemplate, Set<String> columnReferences) {
+			this.sqlTemplate = sqlTemplate;
+			this.columnReferences = columnReferences;
+		}
+
+		public String injectAliases(OrderByAliasResolver aliasResolver) {
+			String sql = sqlTemplate;
+			for ( String columnReference : columnReferences ) {
+				final String replacementToken = "{" + columnReference + "}";
+				sql = sql.replace(
+						replacementToken,
+						aliasResolver.resolveTableAlias( columnReference ) + '.' + columnReference
+				);
+			}
+			return sql;
+		}
+	}
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByTranslation.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByTranslation.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderByTranslation.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,41 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+/**
+ * Represents the result of an order-by translation by {@link @OrderByTranslator}
+ *
+ * @author Steve Ebersole
+ */
+public interface OrderByTranslation {
+	/**
+	 * Inject table aliases into the translated fragment to properly qualify column references, using
+	 * the given 'aliasResolver' to determine the the proper table alias to use for each column reference.
+	 *
+	 * @param aliasResolver The strategy to resolver the proper table alias to use per column
+	 *
+	 * @return The fully translated and replaced fragment.
+	 */
+	public String injectAliases(OrderByAliasResolver aliasResolver);
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderingSpecification.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderingSpecification.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/OrderingSpecification.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,69 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+/**
+ * Models an ordering specification (<tt>ASCENDING</tt> or <tt>DESCENDING</tt>) within a {@link SortSpecification}.
+ *
+ * @author Steve Ebersole
+ */
+public class OrderingSpecification extends NodeSupport {
+	public static class Ordering {
+		public static final Ordering ASCENDING = new Ordering( "asc" );
+		public static final Ordering DESCENDING = new Ordering( "desc" );
+
+		private final String name;
+
+		private Ordering(String name) {
+			this.name = name;
+		}
+	}
+
+	private boolean resolved;
+	private Ordering ordering;
+
+	public Ordering getOrdering() {
+		if ( !resolved ) {
+			ordering = resolve( getText() );
+			resolved = true;
+		}
+		return ordering;
+	}
+
+	private static Ordering resolve(String text) {
+		if ( Ordering.ASCENDING.name.equals( text ) ) {
+			return Ordering.ASCENDING;
+		}
+		else if ( Ordering.DESCENDING.name.equals( text ) ) {
+			return Ordering.DESCENDING;
+		}
+		else {
+			throw new IllegalStateException( "Unknown ordering [" + text + "]" );
+		}
+	}
+
+	public String getRenderableText() {
+		return getOrdering().name;
+	}
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SortKey.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SortKey.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SortKey.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,34 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+
+/**
+ * Models the container node for the <tt>sort key</tt>, which is the term given by the ANSI SQL specification to the
+ * expression upon which to sort for each {@link SortSpecification}
+ *
+ * @author Steve Ebersole
+ */
+public class SortKey extends NodeSupport {
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SortSpecification.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SortSpecification.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SortSpecification.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,79 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+import antlr.collections.AST;
+
+/**
+ * Models each sorting expression.
+ *
+ * @author Steve Ebersole
+ */
+public class SortSpecification extends NodeSupport {
+	/**
+	 * Locate the specified {@link SortKey}.
+	 *
+	 * @return The sort key.
+	 */
+	public SortKey getSortKey() {
+		return ( SortKey ) getFirstChild();
+	}
+
+	/**
+	 * Locate the specified <tt>collation specification</tt>, if one.
+	 *
+	 * @return The <tt>collation specification</tt>, or null if none was specified.
+	 */
+	public CollationSpecification getCollation() {
+		AST possible = getSortKey().getNextSibling();
+		return  possible != null && OrderByTemplateTokenTypes.COLLATE == possible.getType()
+				? ( CollationSpecification ) possible
+				: null;
+	}
+
+	/**
+	 * Locate the specified <tt>ordering specification</tt>, if one.
+	 *
+	 * @return The <tt>ordering specification</tt>, or null if none was specified.
+	 */
+	public OrderingSpecification getOrdering() {
+		// IMPL NOTE : the ordering-spec would be either the 2nd or 3rd child (of the overall sort-spec), if it existed,
+		// 		depending on whether a collation-spec was specified.
+
+		AST possible = getSortKey().getNextSibling();
+		if ( possible == null ) {
+			// There was no sort-spec parts specified other then the sort-key so there can be no ordering-spec...
+			return null;
+		}
+
+		if ( OrderByTemplateTokenTypes.COLLATE == possible.getType() ) {
+			// the 2nd child was a collation-spec, so we need to check the 3rd child instead.
+			possible = possible.getNextSibling();
+		}
+
+		return possible != null && OrderByTemplateTokenTypes.ORDER_SPEC == possible.getType()
+				?  ( OrderingSpecification ) possible
+				:  null;
+	}
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SqlValueReference.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SqlValueReference.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/SqlValueReference.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,36 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+/**
+ * Unifying interface between column and formula references mainly to give more strictly typed result
+ * to {@link ColumnMapper#map(String)}
+ *
+ * @see ColumnReference
+ * @see FormulaReference
+ *
+ * @author Steve Ebersole
+ */
+public interface SqlValueReference {
+}

Added: core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/TranslationContext.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/TranslationContext.java	                        (rev 0)
+++ core/patches/JBPAPP-6940/src/org/hibernate/sql/ordering/antlr/TranslationContext.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -0,0 +1,63 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008 Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ordering.antlr;
+
+import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.function.SQLFunctionRegistry;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+/**
+ * Contract for contextual information required to perform translation.
+*
+* @author Steve Ebersole
+*/
+public interface TranslationContext {
+	/**
+	 * Retrieves the <tt>session factory</tt> for this context.
+	 *
+	 * @return The <tt>session factory</tt>
+	 */
+	public SessionFactoryImplementor getSessionFactory();
+
+	/**
+	 * Retrieves the <tt>dialect</tt> for this context.
+	 *
+	 * @return The <tt>dialect</tt>
+	 */
+	public Dialect getDialect();
+
+	/**
+	 * Retrieves the <tt>SQL function registry/tt> for this context.
+	 *
+	 * @return The SQL function registry.
+	 */
+	public SQLFunctionRegistry getSqlFunctionRegistry();
+
+	/**
+	 * Retrieves the <tt>column mapper</tt> for this context.
+	 *
+	 * @return The <tt>column mapper</tt>
+	 */
+	public ColumnMapper getColumnMapper();
+}

Modified: core/patches/JBPAPP-6940/src/org/hibernate/util/StringHelper.java
===================================================================
--- core/patches/JBPAPP-6940/src/org/hibernate/util/StringHelper.java	2012-08-30 16:52:35 UTC (rev 21064)
+++ core/patches/JBPAPP-6940/src/org/hibernate/util/StringHelper.java	2012-08-30 16:55:39 UTC (rev 21065)
@@ -1,9 +1,10 @@
 //$Id$
 package org.hibernate.util;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.StringTokenizer;
-import java.util.ArrayList;
 
 public final class StringHelper {
 
@@ -62,7 +63,13 @@
 		return buf.toString();
 	}
 
+	public static String repeat(char character, int times) {
+		char[] buffer = new char[times];
+		Arrays.fill( buffer, character );
+		return new String( buffer );
+	}
 
+
 	public static String replace(String template, String placeholder, String replacement) {
 		return replace( template, placeholder, replacement, false );
 	}



More information about the hibernate-commits mailing list