Hibernate SVN: r16441 - in beanvalidation/tags: v1_0_CR2 and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-04-27 04:13:55 -0400 (Mon, 27 Apr 2009)
New Revision: 16441
Added:
beanvalidation/tags/v1_0_CR2/
beanvalidation/tags/v1_0_CR2/pom.xml
Removed:
beanvalidation/tags/v1_0_CR2/pom.xml
Log:
[maven-release-plugin] copy for tag v1_0_CR2
Copied: beanvalidation/tags/v1_0_CR2 (from rev 16400, beanvalidation/trunk/validation-api)
Deleted: beanvalidation/tags/v1_0_CR2/pom.xml
===================================================================
--- beanvalidation/trunk/validation-api/pom.xml 2009-04-22 11:12:04 UTC (rev 16400)
+++ beanvalidation/tags/v1_0_CR2/pom.xml 2009-04-27 08:13:55 UTC (rev 16441)
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <groupId>javax.validation</groupId>
- <artifactId>validation-api</artifactId>
- <version>1.0.CR2-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>Bean Validation API</name>
-
- <description>
- Bean Validation (JSR-303) API.
- </description>
-
- <developers>
- <developer>
- <id>epbernard</id>
- <name>Emmanuel Bernard</name>
- <email>emmanuel(a)hibernate.org</email>
- <organization>JBoss, a division of Red Hat</organization>
- <url>http://in.relation.to/Bloggers/Emmanuel</url>
- </developer>
- <developer>
- <id>hardy.ferentschik</id>
- <name>Hardy Ferentschik</name>
- <email>hferents(a)redhat.com</email>
- <organization>JBoss, a division of Red Hat</organization>
- <url>http://in.relation.to/Bloggers/Hardy</url>
- </developer>
- </developers>
-
- <build>
- <extensions>
- <extension>
- <groupId>org.apache.maven.wagon</groupId>
- <artifactId>wagon-webdav</artifactId>
- <version>1.0-beta-2</version>
- </extension>
- </extensions>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>2.0.2</version>
- <configuration>
- <source>1.5</source>
- <target>1.5</target>
- </configuration>
- </plugin>
- <plugin>
- <artifactId>maven-source-plugin</artifactId>
- <executions>
- <execution>
- <id>attach-sources</id>
- <goals>
- <goal>jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
-
- <issueManagement>
- <system>JIRA</system>
- <url>http://opensource.atlassian.com/projects/hibernate/browse/BVAL</url>
- </issueManagement>
-
- <inceptionYear>2007</inceptionYear>
-
- <licenses>
- <license>
- <name>Apache License, Version 2.0</name>
- <url>license.txt</url>
- </license>
- </licenses>
-
- <scm>
- <connection>scm:https://svn.jboss.org/repos/hibernate/beanvalidation/trunk/validation...</connection>
- <url>http://fisheye.jboss.org/browse/Hibernate/beanvalidation/trunk/validation...</url>
- </scm>
-
-</project>
Copied: beanvalidation/tags/v1_0_CR2/pom.xml (from rev 16440, beanvalidation/trunk/validation-api/pom.xml)
===================================================================
--- beanvalidation/tags/v1_0_CR2/pom.xml (rev 0)
+++ beanvalidation/tags/v1_0_CR2/pom.xml 2009-04-27 08:13:55 UTC (rev 16441)
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ <version>1.0.CR2</version>
+ <packaging>jar</packaging>
+ <name>Bean Validation API</name>
+
+ <description>
+ Bean Validation (JSR-303) API.
+ </description>
+
+ <developers>
+ <developer>
+ <id>epbernard</id>
+ <name>Emmanuel Bernard</name>
+ <email>emmanuel(a)hibernate.org</email>
+ <organization>JBoss, a division of Red Hat</organization>
+ <url>http://in.relation.to/Bloggers/Emmanuel</url>
+ </developer>
+ <developer>
+ <id>hardy.ferentschik</id>
+ <name>Hardy Ferentschik</name>
+ <email>hferents(a)redhat.com</email>
+ <organization>JBoss, a division of Red Hat</organization>
+ <url>http://in.relation.to/Bloggers/Hardy</url>
+ </developer>
+ </developers>
+
+ <build>
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-webdav</artifactId>
+ <version>1.0-beta-2</version>
+ </extension>
+ </extensions>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.0.2</version>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-release-plugin</artifactId>
+ <configuration>
+ <releaseProfiles>release</releaseProfiles>
+ <goals>install</goals>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <issueManagement>
+ <system>JIRA</system>
+ <url>http://opensource.atlassian.com/projects/hibernate/browse/BVAL</url>
+ </issueManagement>
+
+ <inceptionYear>2007</inceptionYear>
+
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>license.txt</url>
+ </license>
+ </licenses>
+
+ <scm>
+ <connection>scm:svn:https://svn.jboss.org/repos/hibernate/beanvalidation/tags/v1_0_CR2</connection>
+ <url>http://fisheye.jboss.org/browse/Hibernate/beanvalidation/tags/v1_0_CR2</url>
+ </scm>
+
+ <profiles>
+ <profile>
+ <id>release</id>
+ <properties>
+ <createChecksum>true</createChecksum>
+ </properties>
+ </profile>
+ </profiles>
+
+</project>
15 years
Hibernate SVN: r16439 - in search/trunk/src: test/java/org/hibernate/search/test/session and 1 other directories.
by hibernate-commits@lists.jboss.org
Author: sannegrinovero
Date: 2009-04-26 17:49:41 -0400 (Sun, 26 Apr 2009)
New Revision: 16439
Added:
search/trunk/src/test/java/org/hibernate/search/test/worker/duplication/WorkSequencesTest.java
Modified:
search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java
search/trunk/src/test/java/org/hibernate/search/test/session/Domain.java
Log:
HSEARCH-353 bugfix (removing an entity and adding another with same PK (in same TX) will not add second entity to index)
Modified: search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java 2009-04-26 03:21:45 UTC (rev 16438)
+++ search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java 2009-04-26 21:49:41 UTC (rev 16439)
@@ -259,16 +259,22 @@
//TODO could we use T instead of EntityClass?
public void addWorkToQueue(Class<T> entityClass, T entity, Serializable id, WorkType workType, List<LuceneWork> queue, SearchFactoryImplementor searchFactoryImplementor) {
//TODO with the caller loop we are in a n^2: optimize it using a HashMap for work recognition
-
+
+ boolean sameIdWasSetToBeDeleted = false;
List<LuceneWork> toDelete = new ArrayList<LuceneWork>();
boolean duplicateDelete = false;
for ( LuceneWork luceneWork : queue ) {
- //avoid unecessary duplicated work
- if ( luceneWork.getEntityClass() == entityClass
- ) {
+ if ( luceneWork.getEntityClass() == entityClass ) {
Serializable currentId = luceneWork.getId();
- //currentId != null => either ADD or Delete work
if ( currentId != null && currentId.equals( id ) ) { //find a way to use Type.equals(x,y)
+ if ( luceneWork instanceof DeleteLuceneWork ) {
+ //flag this work as related to a to-be-deleted entity
+ sameIdWasSetToBeDeleted = true;
+ }
+ else if ( luceneWork instanceof AddLuceneWork ) {
+ //if a later work in the queue is adding it back, undo deletion flag:
+ sameIdWasSetToBeDeleted = false;
+ }
if ( workType == WorkType.DELETE ) { //TODO add PURGE?
//DELETE should have precedence over any update before (HSEARCH-257)
//if an Add work is here, remove it
@@ -280,14 +286,23 @@
duplicateDelete = true;
}
}
- else {
- //we can safely say we are out, the other work is an ADD
- return;
+ if ( workType == WorkType.ADD ) {
+ if ( luceneWork instanceof AddLuceneWork ) {
+ //embedded objects may issue an "UPDATE" right before the "ADD",
+ //leading to double insertions in the index
+ toDelete.add( luceneWork );
+ }
}
+ //TODO do something to avoid multiple PURGE ALL and OPTIMIZE
}
- //TODO do something to avoid multiple PURGE ALL and OPTIMIZE
}
}
+
+ if ( sameIdWasSetToBeDeleted && workType == WorkType.COLLECTION ) {
+ //avoid updating (and thus adding) objects which are going to be deleted
+ return;
+ }
+
for ( LuceneWork luceneWork : toDelete ) {
queue.remove( luceneWork );
}
Modified: search/trunk/src/test/java/org/hibernate/search/test/session/Domain.java
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/session/Domain.java 2009-04-26 03:21:45 UTC (rev 16438)
+++ search/trunk/src/test/java/org/hibernate/search/test/session/Domain.java 2009-04-26 21:49:41 UTC (rev 16439)
@@ -19,6 +19,13 @@
private Integer id;
@Field
private String name;
+
+ public Domain(){ }
+
+ public Domain(Integer id, String name) {
+ this.id = id;
+ this.name = name;
+ }
public Integer getId() {
return id;
Added: search/trunk/src/test/java/org/hibernate/search/test/worker/duplication/WorkSequencesTest.java
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/worker/duplication/WorkSequencesTest.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/worker/duplication/WorkSequencesTest.java 2009-04-26 21:49:41 UTC (rev 16439)
@@ -0,0 +1,124 @@
+package org.hibernate.search.test.worker.duplication;
+
+import java.io.IOException;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
+import org.hibernate.Session;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.search.SearchFactory;
+import org.hibernate.search.reader.ReaderProvider;
+import org.hibernate.search.store.DirectoryProvider;
+import org.hibernate.search.test.SearchTestCase;
+import org.hibernate.search.test.session.Domain;
+
+/**
+ * Testcase for HSEARCH-353
+ * Verify that different kinds of work (add/delete) found in the same
+ * queue are all executed; having special care about different entities
+ * being deleted/persisted but sharing the same PK (to replace the old
+ * instance with another one).
+ *
+ * @author Sanne Grinovero
+ */
+public class WorkSequencesTest extends SearchTestCase {
+
+ private SearchFactory searchFactory;
+
+ public void testComplexTransactionSequence() throws IOException {
+ Session classicSession = openSession( );
+ FullTextSession session = Search.getFullTextSession( classicSession );
+ searchFactory = session.getSearchFactory();
+
+ // create some different domains:
+ {
+ session.beginTransaction();
+ session.persist( new Domain( 1, "jboss.org" ) );
+ session.persist( new Domain( 2, "jboss.com" ) );
+ session.persist( new Domain( 3, "hibernate.org" ) );
+ session.persist( new Domain( 4, "geocities.com" ) );
+ session.getTransaction().commit();
+ }
+ assertEquals( 2, countDomainsByFullText( "jboss" ) );
+ assertEquals( 1, countDomainsByFullText( "hibernate" ) );
+ assertEquals( 1, countDomainsByFullText( "geocities" ) );
+
+ // now create some and delete others:
+ {
+ session.beginTransaction();
+ session.persist( new Domain( 5, "sun.com" ) );
+ session.persist( new Domain( 6, "mysql.com" ) );
+ session.persist( new Domain( 7, "oracle.com" ) );
+ Domain hibernateDomain = (Domain) session.get( Domain.class, 3 );
+ session.delete( hibernateDomain );
+ Domain geocitiesDomain = (Domain) session.get( Domain.class, 4 );
+ session.delete( geocitiesDomain );
+ session.getTransaction().commit();
+ }
+ assertEquals( 0, countDomainsByFullText( "hibernate" ) );
+ assertEquals( 0, countDomainsByFullText( "geocities" ) );
+ assertEquals( 2, countDomainsByFullText( "jboss" ) );
+ assertEquals( 1, countDomainsByFullText( "sun" ) );
+ assertEquals( 1, countDomainsByFullText( "mysql" ) );
+ assertEquals( 1, countDomainsByFullText( "oracle" ) );
+
+ // use create/update/delete:
+ {
+ session.beginTransaction();
+ session.persist( new Domain( 3, "hibernate.org" ) );
+ Domain mysqlDomain = (Domain) session.get( Domain.class, 6 );
+ session.delete( mysqlDomain );
+ //persisting a new entity having the same PK as a deleted one:
+ session.persist( new Domain( 6, "myhql.org" ) );
+ Domain sunDomain = (Domain) session.get( Domain.class, 5 );
+ sunDomain.setName( "community.oracle.com" );
+ session.getTransaction().commit();
+ }
+ assertEquals( 1, countDomainsByFullText( "hibernate" ) );
+ assertEquals( 2, countDomainsByFullText( "oracle" ) );
+ assertEquals( 1, countDomainsByFullText( "myhql" ) );
+ assertEquals( 1, countDomainsByFullText( "community" ) );
+ assertEquals( 0, countDomainsByFullText( "mysql" ) );
+
+ // now creating and deleting the "same" (as by pk) entity several times in same transaction:
+ {
+ session.beginTransaction();
+ session.persist( new Domain( 8, "mysql.org" ) );
+ Domain mysqlDomain = (Domain) session.load( Domain.class, 8 );
+ session.delete( mysqlDomain );
+ Domain newDomain = new Domain( 8, "something.org" );
+ session.persist( newDomain );
+ session.delete( newDomain );
+ session.persist( new Domain( 8, "somethingnew.org" ) );
+ session.getTransaction().commit();
+ }
+ assertEquals( 1, countDomainsByFullText( "somethingnew" ) );
+
+ session.close();
+ }
+
+ //helper method to verify how many instances are found in the index by doing a simple FT query
+ private int countDomainsByFullText(String name) throws IOException {
+ Query luceneQuery = new TermQuery( new Term( "name", name ) );
+ DirectoryProvider<?> directoryProvider = searchFactory.getDirectoryProviders( Domain.class )[0];
+ ReaderProvider readerProvider = searchFactory.getReaderProvider();
+ IndexReader reader = readerProvider.openReader( directoryProvider );
+ IndexSearcher searcher = new IndexSearcher( reader );
+ TopDocs topDocs = searcher.search( luceneQuery, null, 100 );
+ readerProvider.closeReader( reader );
+ return topDocs.totalHits;
+ }
+
+ @Override
+ protected Class<?>[] getMappings() {
+ return new Class[] {
+ Domain.class
+ };
+ }
+
+}
\ No newline at end of file
15 years
Hibernate SVN: r16438 - core/trunk/commons-annotations/src/main/java/org/hibernate/annotations/common/util.
by hibernate-commits@lists.jboss.org
Author: epbernard
Date: 2009-04-25 23:21:45 -0400 (Sat, 25 Apr 2009)
New Revision: 16438
Modified:
core/trunk/commons-annotations/src/main/java/org/hibernate/annotations/common/util/ReflectHelper.java
Log:
fix circular dependency between ReflectHelpers and remove all dependencies.
Modified: core/trunk/commons-annotations/src/main/java/org/hibernate/annotations/common/util/ReflectHelper.java
===================================================================
--- core/trunk/commons-annotations/src/main/java/org/hibernate/annotations/common/util/ReflectHelper.java 2009-04-24 21:05:09 UTC (rev 16437)
+++ core/trunk/commons-annotations/src/main/java/org/hibernate/annotations/common/util/ReflectHelper.java 2009-04-26 03:21:45 UTC (rev 16438)
@@ -23,56 +23,211 @@
*/
package org.hibernate.annotations.common.util;
+import java.lang.reflect.Member;
import java.lang.reflect.Method;
-import java.lang.reflect.Member;
+import java.lang.reflect.Modifier;
+import org.hibernate.AssertionFailure;
+import org.hibernate.util.StringHelper;
+
/**
* Complete duplication of {@link org.hibernate.util.ReflectHelper}.
*
* @author Emmanuel Bernard
*/
public final class ReflectHelper {
+
+ public static final Class[] NO_PARAM_SIGNATURE = new Class[0];
+ public static final Object[] NO_PARAMS = new Object[0];
+
+ public static final Class[] SINGLE_OBJECT_PARAM_SIGNATURE = new Class[] { Object.class };
+
+ private static final Method OBJECT_EQUALS;
+ private static final Method OBJECT_HASHCODE;
+
+ static {
+ Method eq;
+ Method hash;
+ try {
+ eq = extractEqualsMethod( Object.class );
+ hash = extractHashCodeMethod( Object.class );
+ }
+ catch ( Exception e ) {
+ throw new AssertionFailure( "Could not find Object.equals() or Object.hashCode()", e );
+ }
+ OBJECT_EQUALS = eq;
+ OBJECT_HASHCODE = hash;
+ }
+
+ /**
+ * Disallow instantiation of ReflectHelper.
+ */
+ private ReflectHelper() {
+ }
+
+ /**
+ * Encapsulation of getting hold of a class's {@link Object#equals equals} method.
+ *
+ * @param clazz The class from which to extract the equals method.
+ * @return The equals method reference
+ * @throws NoSuchMethodException Should indicate an attempt to extract equals method from interface.
+ */
+ public static Method extractEqualsMethod(Class clazz) throws NoSuchMethodException {
+ return clazz.getMethod( "equals", SINGLE_OBJECT_PARAM_SIGNATURE );
+ }
+
+ /**
+ * Encapsulation of getting hold of a class's {@link Object#hashCode hashCode} method.
+ *
+ * @param clazz The class from which to extract the hashCode method.
+ * @return The hashCode method reference
+ * @throws NoSuchMethodException Should indicate an attempt to extract hashCode method from interface.
+ */
+ public static Method extractHashCodeMethod(Class clazz) throws NoSuchMethodException {
+ return clazz.getMethod( "hashCode", NO_PARAM_SIGNATURE );
+ }
+
+ /**
+ * Determine if the given class defines an {@link Object#equals} override.
+ *
+ * @param clazz The class to check
+ * @return True if clazz defines an equals override.
+ */
public static boolean overridesEquals(Class clazz) {
- return org.hibernate.util.ReflectHelper.overridesEquals( clazz );
+ Method equals;
+ try {
+ equals = extractEqualsMethod( clazz );
+ }
+ catch ( NoSuchMethodException nsme ) {
+ return false; //its an interface so we can't really tell anything...
+ }
+ return !OBJECT_EQUALS.equals( equals );
}
+ /**
+ * Determine if the given class defines a {@link Object#hashCode} override.
+ *
+ * @param clazz The class to check
+ * @return True if clazz defines an hashCode override.
+ */
public static boolean overridesHashCode(Class clazz) {
- return org.hibernate.util.ReflectHelper.overridesHashCode( clazz );
+ Method hashCode;
+ try {
+ hashCode = extractHashCodeMethod( clazz );
+ }
+ catch ( NoSuchMethodException nsme ) {
+ return false; //its an interface so we can't really tell anything...
+ }
+ return !OBJECT_HASHCODE.equals( hashCode );
}
- public static Class classForName(String name) throws ClassNotFoundException {
- return ReflectHelper.classForName( name );
+ /**
+ * Perform resolution of a class name.
+ * <p/>
+ * Here we first check the context classloader, if one, before delegating to
+ * {@link Class#forName(String, boolean, ClassLoader)} using the caller's classloader
+ *
+ * @param name The class name
+ * @param caller The class from which this call originated (in order to access that class's loader).
+ * @return The class reference.
+ * @throws ClassNotFoundException From {@link Class#forName(String, boolean, ClassLoader)}.
+ */
+ public static Class classForName(String name, Class caller) throws ClassNotFoundException {
+ try {
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ if ( contextClassLoader != null ) {
+ return contextClassLoader.loadClass( name );
+ }
+ }
+ catch ( Throwable ignore ) {
+ }
+ return Class.forName( name, true, caller.getClassLoader() );
}
- public static Class classForName(String name, Class caller) throws ClassNotFoundException {
- return org.hibernate.util.ReflectHelper.classForName( name, caller );
+ /**
+ * Perform resolution of a class name.
+ * <p/>
+ * Same as {@link #classForName(String, Class)} except that here we delegate to
+ * {@link Class#forName(String)} if the context classloader lookup is unsuccessful.
+ *
+ * @param name The class name
+ * @return The class reference.
+ * @throws ClassNotFoundException From {@link Class#forName(String)}.
+ */
+ public static Class classForName(String name) throws ClassNotFoundException {
+ try {
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ if ( contextClassLoader != null ) {
+ return contextClassLoader.loadClass(name);
+ }
+ }
+ catch ( Throwable ignore ) {
+ }
+ return Class.forName( name );
}
+ /**
+ * Is this member publicly accessible.
+ *
+ * @param clazz The class which defines the member
+ * @param member The memeber.
+ * @return True if the member is publicly accessible, false otherwise.
+ */
public static boolean isPublic(Class clazz, Member member) {
- return org.hibernate.util.ReflectHelper.isPublic( clazz, member );
+ return Modifier.isPublic( member.getModifiers() ) && Modifier.isPublic( clazz.getModifiers() );
}
+ /**
+ * Resolve a constant to its actual value.
+ *
+ * @param name The name
+ * @return The value
+ */
public static Object getConstantValue(String name) {
- return org.hibernate.util.ReflectHelper.getConstantValue( name );
+ Class clazz;
+ try {
+ clazz = classForName( org.hibernate.util.StringHelper.qualifier( name ) );
+ }
+ catch ( Throwable t ) {
+ return null;
+ }
+ try {
+ return clazz.getField( StringHelper.unqualify( name ) ).get( null );
+ }
+ catch ( Throwable t ) {
+ return null;
+ }
}
+ /**
+ * Determine if the given class is declared abstract.
+ *
+ * @param clazz The class to check.
+ * @return True if the class is abstract, false otherwise.
+ */
public static boolean isAbstractClass(Class clazz) {
- return org.hibernate.util.ReflectHelper.isAbstractClass( clazz );
+ int modifier = clazz.getModifiers();
+ return Modifier.isAbstract(modifier) || Modifier.isInterface(modifier);
}
+ /**
+ * Determine is the given class is declared final.
+ *
+ * @param clazz The class to check.
+ * @return True if the class is final, flase otherwise.
+ */
public static boolean isFinalClass(Class clazz) {
- return org.hibernate.util.ReflectHelper.isFinalClass( clazz );
+ return Modifier.isFinal( clazz.getModifiers() );
}
public static Method getMethod(Class clazz, Method method) {
- return org.hibernate.util.ReflectHelper.getMethod( clazz, method );
+ try {
+ return clazz.getMethod( method.getName(), method.getParameterTypes() );
+ }
+ catch (Exception e) {
+ return null;
+ }
}
- /**
- * Direct instantiation of ReflectHelper disallowed.
- */
- private ReflectHelper() {
- }
-
}
15 years
Hibernate SVN: r16437 - in core/branches/antlr3/src: main/antlr3/org/hibernate/sql/ast/phase/hql/parse and 4 other directories.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2009-04-24 17:05:09 -0400 (Fri, 24 Apr 2009)
New Revision: 16437
Added:
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/ordering/
core/branches/antlr3/src/test/java/org/hibernate/sql/ast/ordering/OrderByParserTest.java
Modified:
core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/ordering/OrderByParser.g
core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/phase/hql/parse/HQLLexer.g
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateTree.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/ordering/OrderByFragmentParser.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/ordering/OrderByFragmentTranslator.java
Log:
first phase of order-by mapping fragment processing using the new unified sql rendering
Modified: core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/ordering/OrderByParser.g
===================================================================
--- core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/ordering/OrderByParser.g 2009-04-24 15:30:34 UTC (rev 16436)
+++ core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/ordering/OrderByParser.g 2009-04-24 21:05:09 UTC (rev 16437)
@@ -1,3 +1,12 @@
+parser grammar OrderByParser;
+
+options {
+ tokenVocab=HQLLexer;
+ output=AST;
+ ASTLabelType=CommonTree;
+}
+
+@parser::header {
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
@@ -21,148 +30,65 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
+ * Portions of SQL grammar parsing copyright (C) 2003 by Lubos Vnuk. All rights
+ * reserved. These portions are distributed under license by Red Hat Middleware
+ * LLC and are covered by the above LGPL notice. If you redistribute this material,
+ * with or without modification, you must preserve this copyright notice in its
+ * entirety.
*/
-grammar OrderByParser;
+package org.hibernate.sql.ast.ordering;
-options {
- language = Java;
- output = AST;
- ASTLabelType = CommonTree;
+import org.hibernate.sql.Template;
}
-tokens {
- COLLATE;
- ASCENDING;
- DESCENDING;
-
- ORDER_BY;
- SORT_SPEC;
- ORDER_SPEC;
- SORT_KEY;
- EXPR_LIST;
- IDENT_LIST;
- COLUMN_REF;
-
- NUM_INTEGER_LITERAL;
- NUM_LONG_LITERAL;
- NUM_DOUBLE_LITERAL;
- NUM_FLOAT_LITERAL;
-}
-
-@lexer::header {
- package org.hibernate.sql.ast.ordering;
-}
-
-@lexer::members {
-}
-
-@parser::header {
- package org.hibernate.sql.ast.ordering;
-
- import org.hibernate.sql.Template;
- import org.hibernate.dialect.function.SQLFunction;
-}
-
@parser::members {
/**
- * Process the given node as a quote identifier. These need to be quoted in the dialect-specific way.
+ * A check to see if the text represents a known function name (in addition to the
+ * set of known {@link #standardFunction "standard"} functions. This is only needed in the
+ * case of seeing a dot-ident structure which is not followed by a paren; such structures
+ * which are followed by a paren are explicitly assumed to be a function name.
*
- * @param ident The quoted-identifier node.
+ * @param text The text to check as a function name.
*
- * @return The processed node.
- */
- protected CommonTree quotedIdentifier(CommonTree ident) {
- // here we assume single-quote as the identifier quote character...
- return createTreeNode( IDENTIFIER, Template.TEMPLATE + ".'" + ident.getText() + "'" );
- }
-
-
- /**
- * Process the given node as a quote string.
+ * @return True if the text is a known function name, false otherwise.
*
- * @param token The quoted string. This is used from within function param recognition, and represents a
- * SQL-quoted string.
- *
- * @return The processed node.
+ * @see #standardFunction
*/
- protected CommonTree quotedString(Token token) {
- return createTreeNode( STRING_LITERAL, "'" + token.getText() + "'" );
+ protected boolean isFunctionName(String text) {
+ // by default, assume it is not
+ return false;
}
/**
- * A check to see if the text of the given node represents a known function name.
+ * A check to see if the text represents a mapped property name.
*
- * @param token The node whose text we want to check.
+ * @param text The text to check as a property name.
*
- * @return True if the node's text is a known function name, false otherwise.
- *
- * @see org.hibernate.dialect.function.SQLFunctionRegistry
+ * @return True if the text is a mapped property name, false otherwise.
*/
- protected boolean isFunctionName(Token token) {
+ protected boolean isPropertyName(String text) {
+ // by default, assume it is not
return false;
}
/**
- * Process the given node as a function name. Differs from {@link #resolveFunction(org.antlr.runtime.tree.CommonTree)
- * specifically in that here we are expecting just a function name without parens or arguments.
+ * Given a property, resolve it's {@link #COLUMN} or {@link #VECTOR_EXPR} tree.
*
- * @param token The token representing the function name.
+ * @param propertyTree The tree representing the property name.
*
- * @return The processed node.
+ * @return The column(s) tree.
*/
- protected CommonTree resolveFunction(Token token) {
- return resolveFunction( new CommonTree( token ) );
+ protected CommonTree buildPropertyColumns(CommonTree propertyTree) {
+ throw new UnsupportedOperationException( "must be overridden!" );
}
- /**
- * Process the given node as a function.
- *
- * @param tree The node representing the function invocation (including parameters as subtree components).
- *
- * @return The processed node.
- */
- protected CommonTree resolveFunction(CommonTree tree) {
- Tree argumentList = tree.getChild( 0 );
- assert argumentList == null || "{param list}".equals( argumentList.getText() );
-
- String text = tree.getText();
- int count = argumentList == null ? 0 : argumentList.getChildCount();
- if ( count > 0 ) {
- text += '(';
- for ( int i = 0; i < count; i++ ) {
- Tree argument = argumentList.getChild( i );
- text += argument.getText();
- if ( i < count ) {
- text += ", ";
- }
- }
- text += ')';
- }
- return createTreeNode( IDENTIFIER, text );
- }
-
- protected CommonTree resolveIdent(Token token) {
- return resolveIdent( new CommonTree( token ) );
- }
-
- /**
- * Process the given node as an IDENTIFIER. 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 CommonTree resolveIdent(CommonTree ident) {
- return createTreeNode( IDENTIFIER, Template.TEMPLATE + "." + ident.getText() );
- }
-
- private boolean validateIdentifierAsKeyword(String text) {
- return validateLT( 1, text );
+ private boolean validateSoftKeyword(String text) {
+ return validateLT(1, text);
}
private boolean validateLT(int offset, String text) {
String text2Validate = retrieveLT( offset );
- return text2Validate == null ? false : text2Validate.equalsIgnoreCase(text);
+ return text2Validate == null ? false : text2Validate.equalsIgnoreCase( text );
}
private String retrieveLT(int offset) {
@@ -172,10 +98,6 @@
Token token = input.LT(offset);
return token == null ? null : token.getText();
}
-
- protected CommonTree createTreeNode(int type, String text) {
- return new CommonTree( new CommonToken( type, text ) );
- }
}
@@ -185,17 +107,19 @@
/**
* Main recognition rule for this grammar
*/
-orderByFragment
- : sortSpecification ( ',' sortSpecification )* -> ^( ORDER_BY sortSpecification+ )
- ;
+orderByFragment :
+ sortSpecification ( COMMA sortSpecification )*
+ -> ^( ORDER_BY sortSpecification+ )
+;
/**
- * Reconition rule for what ANSI SQL terms the <tt>sort specification</tt>, which is essentially each thing upon which
- * the results should be sorted.
+ * Reconition rule for what ANSI SQL terms the <tt>sort specification</tt>. These are the atomic elements of the
+ * <tt>ORDER BY</tt> list pieces.
*/
-sortSpecification
- : sortKey collationSpecification? orderingSpecification? -> ^( SORT_SPEC sortKey collationSpecification? orderingSpecification? )
+sortSpecification :
+ sortKey collationSpecification? orderingSpecification?
+ -> ^( SORT_SPEC sortKey collationSpecification? orderingSpecification? )
;
@@ -203,213 +127,441 @@
* Reconition 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
- : expression -> ^( SORT_KEY expression )
+sortKey :
+ expression
;
/**
* Reconition rule what this grammar recognizes as valid <tt>sort key</tt>.
*/
expression
- : hardQuoteExpression
- | ( IDENTIFIER ('.' IDENTIFIER)* OPEN_PAREN ) => functionCall
- | simplePropertyPath
- | IDENTIFIER -> {isFunctionName($IDENTIFIER)}? { resolveFunction( $IDENTIFIER ) }
- -> { resolveIdent( $IDENTIFIER ) }
+ : QUOTED_IDENTIFIER -> ^( COLUMN[$QUOTED_IDENTIFIER] ALIAS_REF[Template.TEMPLATE] QUOTED_IDENTIFIER[$QUOTED_IDENTIFIER] )
+ // we treat the so-called standard functions differently because they are handled differently by the HQL lexer which we also use here...
+ | standardFunction
+ // not identDotIdentStructure because we dont want QUOTED_IDENTIFIERs is here
+ | ( IDENTIFIER ( DOT IDENTIFIER )* LEFT_PAREN ) => generalFunction
+ // otherwise we fully expect a dot-identifier series, and then we just need to decode the semantic of that structure
+ | identDotIdentStructure
+ -> { ( isFunctionName($identDotIdentStructure.text) ) }?
+ // we have a function with parens (thus no args)
+ ^( GENERAL_FUNCTION_CALL[$identDotIdentStructure.start,$identDotIdentStructure.text] )
+ -> { ( isPropertyName($identDotIdentStructure.text) ) }?
+ // we have a reference to a mapped property
+ { buildPropertyColumns( $identDotIdentStructure.tree ) }
+ -> { ( $identDotIdentStructure.tree.getType() == DOT ) }?
+ // we have a reference to a column which is already qualified
+ identDotIdentStructure
+ ->
+ // we have a reference to a column which is not qualified
+ ^( COLUMN ALIAS_REF[Template.TEMPLATE] IDENTIFIER[$identDotIdentStructure.start,$identDotIdentStructure.text] )
+ ;
+
+fragment
+identifier
+ : IDENTIFIER
+ | QUOTED_IDENTIFIER
+ ;
+
+fragment
+identDotIdentStructure
+ : IDENTIFIER ( DOT^ identifier )*
+ ;
+
+standardFunction
+ : castFunction
+ | concatFunction
+ | substringFunction
+ | trimFunction
+ | upperFunction
+ | lowerFunction
+ | lengthFunction
+ | locateFunction
+ | absFunction
+ | sqrtFunction
+ | modFunction
+ | currentDateFunction
+ | currentTimeFunction
+ | currentTimestampFunction
+ | extractFunction
+ | positionFunction
+ | charLengthFunction
+ | octetLengthFunction
+ | bitLengthFunction
;
-hardQuoteExpression
-@after { $tree = quotedIdentifier( $tree ); }
- : HARD_QUOTE IDENTIFIER HARD_QUOTE -> IDENTIFIER
+castFunction
+ : cast_keyword^ LEFT_PAREN! expression as_keyword! dataType RIGHT_PAREN!
;
-/**
- * Recognition rule for a function call
- */
-functionCall
-@after { $tree = resolveFunction( $tree ); }
- : functionName OPEN_PAREN functionParameterList CLOSE_PAREN -> ^( functionName functionParameterList )
+fragment
+dataType
+ : IDENTIFIER
;
-/**
- * A function-name is an IDENTIFIER followed by zero or more (DOT IDENTIFIER) sequences
- */
-functionName returns [String nameText]
- : i=IDENTIFIER { $nameText = $i.text; } ( '.' i=IDENTIFIER { $nameText += ( '.' + $i.text ); } )+
+concatFunction
+ : concat_keyword^ LEFT_PAREN! expression ( COMMA! expression )+ RIGHT_PAREN!
;
+substringFunction
+ : substring_keyword^ LEFT_PAREN! expression COMMA! expression ( COMMA! expression)? RIGHT_PAREN!
+ ;
+
+trimFunction
+ : trim_keyword LEFT_PAREN trimOperands RIGHT_PAREN
+ -> ^(trim_keyword trimOperands)
+ ;
+
+fragment
+trimOperands
+options{
+k=2;
+}
+@init {boolean hasSecondExpression = false;}
+ : trimSpecification from_keyword expression -> ^(trimSpecification STRING_LITERAL[" "] expression)
+ | trimSpecification expression from_keyword expression -> ^(trimSpecification expression+)
+ | from_keyword expression -> ^(BOTH STRING_LITERAL[" "] expression)
+ | cn=expression ( from_keyword expression {hasSecondExpression = true;} )?
+ -> {hasSecondExpression}? ^(BOTH expression+)
+ -> ^(BOTH STRING_LITERAL[" "] $cn)
+ ;
+
+fragment
+trimSpecification
+ : leading_keyword
+ | trailing_keyword
+ | both_keyword
+ ;
+
+upperFunction
+ : upper_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ ;
+
+lowerFunction
+ : lower_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ ;
+
+lengthFunction
+ : length_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ ;
+
+locateFunction
+ : locate_keyword^ LEFT_PAREN! expression COMMA! expression ( COMMA! expression )? RIGHT_PAREN!
+ ;
+
+absFunction
+ : abs_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ ;
+
+sqrtFunction
+ : sqrt_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ ;
+
+modFunction
+ : mod_keyword^ LEFT_PAREN! expression COMMA! expression RIGHT_PAREN!
+ ;
+
+currentDateFunction
+ : current_date_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
+ ;
+
+currentTimeFunction
+ : current_time_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
+ ;
+
+currentTimestampFunction
+ : current_timestamp_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
+ ;
+
+extractFunction
+ : extract_keyword^ LEFT_PAREN! extractField from_keyword! expression RIGHT_PAREN!
+ ;
+
+extractField
+ : datetimeField
+ | timeZoneField
+ ;
+
+datetimeField
+ : nonSecondDatetimeField
+ | second_keyword
+ ;
+
+nonSecondDatetimeField
+ : year_keyword
+ | month_keyword
+ | day_keyword
+ | hour_keyword
+ | minute_keyword
+ ;
+
+timeZoneField
+ : timezone_hour_keyword
+ | timezone_minute_keyword
+ ;
+
+positionFunction
+ : position_keyword^ LEFT_PAREN! expression in_keyword! expression RIGHT_PAREN!
+ ;
+
+charLengthFunction
+ : character_length_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ ;
+
+octetLengthFunction
+ : octet_length_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ ;
+
+bitLengthFunction
+ : bit_length_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+ ;
+
+
+generalFunction
+ : generalFunctionName LEFT_PAREN functionArgumentList RIGHT_PAREN
+ -> ^( GENERAL_FUNCTION_CALL[$generalFunctionName.start,$generalFunctionName.text] functionArgumentList )
+ ;
+
+generalFunctionName :
+ IDENTIFIER ( DOT IDENTIFIER )+
+;
+
/**
- * Recognition rule used to "wrap" all function parameters into an EXPR_LIST node
+ * Recognition rule used to "wrap" all function arguments into a GENERAL_FUNCTION_ARGUMENTS node
*/
-functionParameterList
- : functionParameter ( COMMA functionParameter )* -> ^( EXPR_LIST functionParameter+ )
- ;
+functionArgumentList :
+ functionArgument ( COMMA functionArgument )*
+ -> ^( GENERAL_FUNCTION_ARGUMENTS functionArgument+ )
+;
/**
* Recognized function parameters.
*/
-functionParameter :
+functionArgument :
expression
- | numericLiteral
- | qs=STRING_LITERAL -> { quotedString( $qs ) }
+ | literal
;
-numericLiteral
- : HEX_LITERAL
- | OCTAL_LITERAL
- | DECIMAL_LITERAL
- | FLOATING_POINT_LITERAL
+literal
+ : numeric_literal
+ | HEX_LITERAL
+ | OCTAL_LITERAL
+ | CHARACTER_LITERAL
+ | STRING_LITERAL
;
+numeric_literal
+ : INTEGER_LITERAL
+ | DECIMAL_LITERAL
+ | FLOATING_POINT_LITERAL
+ ;
/**
* Reconition 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! :
- collateKeyword collationName -> { createTreeNode(COLLATE, $collationName.text) }
+collationSpecification!
+ : collateKeyword collationName
+ -> COLLATE[$collateKeyword.start,$collationName.text]
;
-collateKeyword
- : {(validateIdentifierAsKeyword("collate"))}?=> id=IDENTIFIER
+collateKeyword :
+ {(validateSoftKeyword("collate"))}?=> id=IDENTIFIER
-> COLLATE[$id]
+;
- ;
-
/**
* The collation name wrt {@link #collationSpecification}. Namely, the character-set.
*/
-collationName
- : IDENTIFIER
- ;
+collationName :
+ IDENTIFIER
+;
/**
* Reconition rule for what ANSI SQL terms the <tt>ordering specification</tt>; <tt>ASCENDING</tt> or
* <tt>DESCENDING</tt>.
*/
-orderingSpecification!
- : ( 'asc' | 'ascending' ) -> { createTreeNode(ORDER_SPEC,"asc") }
- | ( 'desc' | 'descending') -> { createTreeNode(ORDER_SPEC,"desc" ) }
+orderingSpecification! :
+ ascending_keyword
+ -> ORDER_SPEC[$ascending_keyword.start,"asc"]
+ | descending_keyword
+ -> ORDER_SPEC[$descending_keyword.start,"desc"]
+;
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Soft-keyword handling rules
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+abs_keyword
+ : {(validateSoftKeyword("abs"))}?=> id=IDENTIFIER
+ -> ABS[$id]
;
-/**
- * A simple-property-path is an IDENTIFIER followed by one or more (DOT IDENTIFIER) sequences
- */
-simplePropertyPath
-@after { $tree = resolveIdent($tree); }
- : p=simplePropertyPathText -> { createTreeNode(IDENTIFIER, $p.pathText) }
+as_keyword
+ : {(validateSoftKeyword("as"))}?=> id=IDENTIFIER
+ -> AS[$id]
;
-simplePropertyPathText returns [String pathText]
- : i=IDENTIFIER { $pathText = $i.text; } ( '.' i=IDENTIFIER { $pathText += ( '.' + $i.text ); } )+
+ascending_keyword :
+ {(validateSoftKeyword("ascending") || validateSoftKeyword("asc"))}?=> IDENTIFIER
+;
+
+bit_length_keyword
+ : {(validateSoftKeyword("bit_length"))}?=> id=IDENTIFIER
+ -> BIT_LENGTH[$id]
;
+both_keyword
+ : {(validateSoftKeyword("both"))}?=> id=IDENTIFIER
+ -> BOTH[$id]
+ ;
+cast_keyword
+ : {(validateSoftKeyword("cast"))}?=> id=IDENTIFIER
+ -> CAST[$id]
+ ;
-// Lexer rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+character_length_keyword
+ : {(validateSoftKeyword("character_length") || validateSoftKeyword("char_length"))}?=> id=IDENTIFIER
+ -> CHARACTER_LENGTH[$id]
+ ;
-WS
- : (SPACE | EOL | '\u000C') { $channel=HIDDEN; }
- ;
+concat_keyword
+ : {(validateSoftKeyword("concat"))}?=> id=IDENTIFIER
+ -> CONCAT[$id]
+ ;
-fragment
-EOL
- : ( '\r' (options{greedy=true;}: '\n')? | '\n' )
- ;
+current_date_keyword
+ : {(validateSoftKeyword("current_date"))}?=> id=IDENTIFIER
+ -> CURRENT_DATE[$id]
+ ;
-fragment
-SPACE
- : ' '
- | '\t'
- ;
+current_time_keyword
+ : {(validateSoftKeyword("current_time"))}?=> id=IDENTIFIER
+ -> CURRENT_TIME[$id]
+ ;
-OPEN_PAREN
- : '('
- ;
-CLOSE_PAREN
- : ')'
- ;
+current_timestamp_keyword
+ : {(validateSoftKeyword("current_timestamp"))}?=> id=IDENTIFIER
+ -> CURRENT_TIMESTAMP[$id]
+ ;
-COMMA
- : ','
- ;
+day_keyword
+ : {(validateSoftKeyword("day"))}?=> id=IDENTIFIER
+ -> DAY[$id]
+ ;
-HARD_QUOTE
- : '`'
- ;
+descending_keyword :
+ {(validateSoftKeyword("descending") || validateSoftKeyword("desc"))}?=> IDENTIFIER
+;
-INTEGER_LITERAL
- : (
- '0'
- | '1'..'9' ('0'..'9')*
- )
- ;
+extract_keyword
+ : {(validateSoftKeyword("extract"))}?=> id=IDENTIFIER
+ -> EXTRACT[$id]
+ ;
-DECIMAL_LITERAL : ('0' | '1'..'9' '0'..'9'*) INTEGER_TYPE_SUFFIX ;
+from_keyword
+ : {(validateSoftKeyword("from"))}?=> id=IDENTIFIER
+ -> FROM[$id]
+ ;
-HEX_LITERAL
- : '0' ('x'|'X') HEX_DIGIT+ INTEGER_TYPE_SUFFIX?
- ;
+hour_keyword
+ : {(validateSoftKeyword("hour"))}?=> id=IDENTIFIER
+ -> HOUR[$id]
+ ;
-OCTAL_LITERAL : '0' ('0'..'7')+ INTEGER_TYPE_SUFFIX? ;
+in_keyword
+ : {(validateSoftKeyword("in"))}?=> id=IDENTIFIER
+ -> IN[$id]
+ ;
+leading_keyword
+ : {(validateSoftKeyword("leading"))}?=> id=IDENTIFIER
+ -> LEADING[$id]
+ ;
+length_keyword
+ : {(validateSoftKeyword("length"))}?=> id=IDENTIFIER
+ -> LENGTH[$id]
+ ;
-fragment
-HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
+locate_keyword
+ : {(validateSoftKeyword("locate"))}?=> id=IDENTIFIER
+ -> LOCATE[$id]
+ ;
-fragment
-INTEGER_TYPE_SUFFIX : ('l'|'L') ;
+lower_keyword
+ : {(validateSoftKeyword("lower"))}?=> id=IDENTIFIER
+ -> LOWER[$id]
+ ;
-FLOATING_POINT_LITERAL
- : ('0'..'9')+ '.' ('0'..'9')* EXPONENT? FLOAT_TYPE_SUFFIX?
- | '.' ('0'..'9')+ EXPONENT? FLOAT_TYPE_SUFFIX?
- | ('0'..'9')+ EXPONENT FLOAT_TYPE_SUFFIX?
- | ('0'..'9')+ FLOAT_TYPE_SUFFIX
- ;
+minute_keyword
+ : {(validateSoftKeyword("minute"))}?=> id=IDENTIFIER
+ -> MINUTE[$id]
+ ;
-fragment
-EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;
+mod_keyword
+ : {(validateSoftKeyword("mod"))}?=> id=IDENTIFIER
+ -> MOD[$id]
+ ;
-fragment
-FLOAT_TYPE_SUFFIX : ('f'|'F'|'d'|'D') ;
+month_keyword
+ : {(validateSoftKeyword("month"))}?=> id=IDENTIFIER
+ -> MONTH[$id]
+ ;
+octet_length_keyword
+ : {(validateSoftKeyword("octet_length"))}?=> id=IDENTIFIER
+ -> OCTET_LENGTH[$id]
+ ;
-STRING_LITERAL
- : '\'' ( ESCAPE_SEQUENCE | ~('\''|'\\') ) '\''
- ;
+position_keyword
+ : {(validateSoftKeyword("position"))}?=> id=IDENTIFIER
+ -> POSITION[$id]
+ ;
-fragment
-ESCAPE_SEQUENCE
- : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
- | UNICODE_ESCAPE
- | OCTAL_ESCAPE
- ;
+second_keyword
+ : {(validateSoftKeyword("second"))}?=> id=IDENTIFIER
+ -> SECOND[$id]
+ ;
-fragment
-OCTAL_ESCAPE
- : '\\' ('0'..'3') ('0'..'7') ('0'..'7')
- | '\\' ('0'..'7') ('0'..'7')
- | '\\' ('0'..'7')
- ;
+sqrt_keyword
+ : {(validateSoftKeyword("sqrt"))}?=> id=IDENTIFIER
+ -> SQRT[$id]
+ ;
-fragment
-UNICODE_ESCAPE
- : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
- ;
+substring_keyword
+ : {(validateSoftKeyword("substring"))}?=> id=IDENTIFIER
+ -> SUBSTRING[$id]
+ ;
-IDENTIFIER
- : IDENTIFIER_START_FRAGMENT (IDENTIFER_FRAGMENT)*
+timezone_hour_keyword
+ : {(validateSoftKeyword("timezone_hour"))}?=> id=IDENTIFIER
+ -> TIMEZONE_HOUR[$id]
;
-fragment
-IDENTIFIER_START_FRAGMENT
- : ('a'..'z'|'A'..'Z'|'_'|'$'|'\u0080'..'\ufffe')
- ;
+timezone_minute_keyword
+ : {(validateSoftKeyword("timezone_minute"))}?=> id=IDENTIFIER
+ -> TIMEZONE_MINUTE[$id]
+ ;
-fragment
-IDENTIFER_FRAGMENT
- : IDENTIFIER_START_FRAGMENT
- | '0'..'9'
- ;
+trailing_keyword
+ : {(validateSoftKeyword("trailing"))}?=> id=IDENTIFIER
+ -> TRAILING[$id]
+ ;
+trim_keyword
+ : {(validateSoftKeyword("trim"))}?=> id=IDENTIFIER
+ -> TRIM[$id]
+ ;
+
+upper_keyword
+ : {(validateSoftKeyword("upper"))}?=> id=IDENTIFIER
+ -> UPPER[$id]
+ ;
+
+year_keyword
+ : {(validateSoftKeyword("year"))}?=> id=IDENTIFIER
+ -> YEAR[$id]
+ ;
+
Modified: core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/phase/hql/parse/HQLLexer.g
===================================================================
--- core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/phase/hql/parse/HQLLexer.g 2009-04-24 15:30:34 UTC (rev 16436)
+++ core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/phase/hql/parse/HQLLexer.g 2009-04-24 21:05:09 UTC (rev 16437)
@@ -19,6 +19,7 @@
ENTITY_PERSISTER_REF;
FILTER;
GENERAL_FUNCTION_CALL;
+ GENERAL_FUNCTION_ARGUMENTS;
GROUPING_VALUE;
IN_LIST;
INSERTABILITY_SPEC;
@@ -32,6 +33,7 @@
NOT_IN;
NOT_LIKE;
NOT_MEMBER_OF;
+ ORDER_SPEC;
PATH;
PERSISTER_JOIN;
PERSISTER_SPACE;
@@ -122,7 +124,6 @@
ON;
OR;
ORDER_BY;
- ORDER_SPEC;
OUTER;
POSITION;
PROPERTIES;
@@ -233,7 +234,6 @@
STRING_LITERAL
: '"' ( ESCAPE_SEQUENCE | ~('\\'|'"') )* '"'
| ('\'' ( ESCAPE_SEQUENCE | ~('\\'|'\'') )* '\'')+
- | '`' ( ESCAPE_SEQUENCE | ~('\\'|'`') )* '`'
;
fragment
@@ -320,6 +320,10 @@
: ('a'..'z'|'A'..'Z'|'_'|'$'|'\u0080'..'\ufffe')('a'..'z'|'A'..'Z'|'_'|'$'|'0'..'9'|'\u0080'..'\ufffe')*
;
+QUOTED_IDENTIFIER
+ : '`' ( ESCAPE_SEQUENCE | ~('\\'|'`') )* '`'
+ ;
+
LEFT_PAREN
: '('
;
Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java 2009-04-24 15:30:34 UTC (rev 16436)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java 2009-04-24 21:05:09 UTC (rev 16437)
@@ -26,7 +26,6 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-
package org.hibernate.sql.ast.common;
import org.antlr.runtime.CommonToken;
@@ -37,34 +36,34 @@
* Models the token-type/text portion of an Antlr tree for a specific node in said tree.
*
* @author Steve Ebersole
+ * @author Alexandre Porcelli
*/
public class HibernateToken extends CommonToken {
- public HibernateToken(int type) {
- super(type);
- }
+ public HibernateToken(int type) {
+ super( type );
+ }
- public HibernateToken(CharStream input, int type, int channel, int start,
- int stop) {
- super(input, type, channel, start, stop);
- }
+ public HibernateToken(CharStream input, int type, int channel, int start, int stop) {
+ super( input, type, channel, start, stop );
+ }
- public HibernateToken(int type, String text) {
- super(type, text);
- }
+ public HibernateToken(int type, String text) {
+ super( type, text );
+ }
- /**
- * Constructor that preserves the char offset
- *
- * @param oldToken
- */
- public HibernateToken(Token oldToken) {
- super(oldToken);
- if (null != oldToken
- && (oldToken.getClass().equals(CommonToken.class) || oldToken
- .getClass().equals(HibernateToken.class))) {
- start = ((CommonToken) oldToken).getStartIndex();
- stop = ((CommonToken) oldToken).getStopIndex();
- }
- }
+ /**
+ * Constructor that preserves the char offset
+ *
+ * @param oldToken A token to use to template the creation of this new one.
+ */
+ public HibernateToken(Token oldToken) {
+ super( oldToken );
+ if ( null != oldToken
+ && ( oldToken.getClass().equals( CommonToken.class ) || oldToken
+ .getClass().equals( HibernateToken.class ) ) ) {
+ start = ( ( CommonToken ) oldToken ).getStartIndex();
+ stop = ( ( CommonToken ) oldToken ).getStopIndex();
+ }
+ }
}
Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateTree.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateTree.java 2009-04-24 15:30:34 UTC (rev 16436)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateTree.java 2009-04-24 21:05:09 UTC (rev 16437)
@@ -36,6 +36,7 @@
* todo : javadocs
*
* @author Steve Ebersole
+ * @author Alexandre Porcelli
*/
public class HibernateTree extends CommonTree {
/**
Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/ordering/OrderByFragmentParser.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/ordering/OrderByFragmentParser.java 2009-04-24 15:30:34 UTC (rev 16436)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/ordering/OrderByFragmentParser.java 2009-04-24 21:05:09 UTC (rev 16437)
@@ -24,172 +24,86 @@
*/
package org.hibernate.sql.ast.ordering;
-import java.util.ArrayList;
-
-import org.hibernate.sql.Template;
-import org.hibernate.dialect.function.SQLFunction;
-import org.hibernate.util.StringHelper;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.antlr.runtime.TokenStream;
-import org.antlr.runtime.CommonToken;
import org.antlr.runtime.tree.CommonTree;
-import org.antlr.runtime.tree.Tree;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.hibernate.sql.ast.common.HibernateTree;
+import org.hibernate.sql.Template;
+
/**
* Extension of the Antlr-generated parser for the purpose of adding our custom parsing behavior.
*
* @author Steve Ebersole
*/
-public class OrderByFragmentParser extends OrderByParserParser {
+public class OrderByFragmentParser extends OrderByParser {
private static final Logger log = LoggerFactory.getLogger( OrderByFragmentParser.class );
-
private final TranslationContext context;
- private int traceDepth = 0;
+ private final String openQuoteChar;
+ private final String closeQuoteChar;
+
public OrderByFragmentParser(TokenStream lexer, TranslationContext context) {
super( lexer );
this.context = context;
+
+ this.openQuoteChar = Character.toString( context.getDialect().openQuote() );
+ this.closeQuoteChar = Character.toString( context.getDialect().closeQuote() );
}
-//
-//
-// // handle trace logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// public void traceIn(String ruleName) throws TokenStreamException {
-// if ( inputState.guessing > 0 ) {
-// return;
-// }
-// String prefix = StringHelper.repeat( "-", (traceDepth++ * 2) ) + "->";
-// trace( prefix + ruleName );
-// }
-//
-// public void traceOut(String ruleName) throws TokenStreamException {
-// if ( inputState.guessing > 0 ) {
-// return;
-// }
-// String prefix = "<-" + StringHelper.repeat( "-", (--traceDepth * 2) );
-// trace( prefix + ruleName );
-// }
-//
-// private void trace(String msg) {
-// log.trace( msg );
-// }
-protected CommonTree quotedIdentifier(CommonTree ident) {
- return createTreeNode( IDENTIFIER, Template.TEMPLATE + "." + context.getDialect().quote( '`' + ident.getText() + '`' ) );
-}
-
- protected CommonTree quotedString(CommonTree ident) {
- return createTreeNode( IDENTIFIER, context.getDialect().quote( ident.getText() ) );
+ @Override
+ protected boolean isFunctionName(String text) {
+ log.trace( "Checking function name [" + text + "]" );
+ return context.getSqlFunctionRegistry().hasFunction( text );
}
- protected boolean isFunctionName(CommonToken token) {
- return context.getSqlFunctionRegistry().hasFunction( token.getText() );
- }
-
- protected CommonTree resolveFunction(CommonTree tree) {
- Tree argumentList = tree.getChild( 0 );
- assert "{param list}".equals( argumentList.getText() );
-
- final String functionName = tree.getText();
- final SQLFunction function = context.getSqlFunctionRegistry().findSQLFunction( functionName );
-
- if ( function == null ) {
- // If the function is not registered with the session factory we just need to render it as-is
- // including its arguments...
- String text = functionName;
- int count = argumentList.getChildCount();
- if ( count > 0 ) {
- text += '(';
- for ( int i = 0; i < count; i++ ) {
- Tree argument = argumentList.getChild( i );
- text += argument.getText();
- if ( i < count ) {
- text += ", ";
- }
- }
- text += ')';
- }
- return createTreeNode( IDENTIFIER, text );
+ @Override
+ protected boolean isPropertyName(String text) {
+ log.trace( "Checking property name [" + text + "]" );
+ try {
+ return context.getColumnMapper().map( text ) != null;
}
- else {
- ArrayList expressions = new ArrayList();
- for ( int i = 0; i < argumentList.getChildCount(); i++ ) {
- expressions.add( argumentList.getChild( i ).getText() );
- }
- final String text = function.render( expressions, context.getSessionFactory() );
- return createTreeNode( IDENTIFIER, text );
+ catch ( Throwable t ) {
+ return false;
}
}
- protected CommonTree resolveIdent(CommonTree ident) {
- String text = ident.getText();
- String[] replacements;
- try {
- replacements = context.getColumnMapper().map( text );
+ @Override
+ protected CommonTree buildPropertyColumns(CommonTree propertyTree) {
+ final String text = extractPropertyName( propertyTree );
+ String[] columns = context.getColumnMapper().map( text );
+ if ( columns.length == 1 ) {
+ return buildColumn( columns[0] );
}
- catch( Throwable t ) {
- replacements = null;
+ else {
+ HibernateTree vector = new HibernateTree( VECTOR_EXPR );
+ for ( String column : columns ) {
+ vector.addChild( buildColumn( column ) );
+ }
+ return vector;
}
+ }
- if ( replacements == null || replacements.length == 0 ) {
- return createTreeNode( IDENTIFIER, Template.TEMPLATE + "." + text );
+ private CommonTree buildColumn(String columnName) {
+ // ugh
+ HibernateTree columnNameNode;
+ if ( columnName.startsWith( openQuoteChar ) && columnName.endsWith( closeQuoteChar ) ) {
+ columnName = columnName.substring( 1, columnName.length() - 1 );
+ columnNameNode = new HibernateTree( QUOTED_IDENTIFIER, columnName );
}
- else if ( replacements.length == 1 ) {
- return createTreeNode( IDENTIFIER, Template.TEMPLATE + "." + replacements[0] );
- }
else {
- final CommonTree root = createTreeNode( IDENT_LIST, "{ident list}" );
- for ( int i = 0; i < replacements.length; i++ ) {
- final String identText = Template.TEMPLATE + '.' + replacements[i];
- root.addChild( createTreeNode( IDENTIFIER, identText ) );
- }
- return root;
+ columnNameNode = new HibernateTree( IDENTIFIER, columnName );
}
+
+ HibernateTree tree = new HibernateTree( COLUMN );
+ tree.addChild( new HibernateTree( ALIAS_REF, Template.TEMPLATE ) );
+ tree.addChild( columnNameNode );
+
+ return tree;
}
-//
-// /**
-// * {@inheritDoc}
-// */
-// 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;
-// }
+
+ private String extractPropertyName(CommonTree propertyTree) {
+ return propertyTree.getText();
+ }
}
Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/ordering/OrderByFragmentTranslator.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/ordering/OrderByFragmentTranslator.java 2009-04-24 15:30:34 UTC (rev 16436)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/ordering/OrderByFragmentTranslator.java 2009-04-24 21:05:09 UTC (rev 16437)
@@ -24,15 +24,13 @@
*/
package org.hibernate.sql.ast.ordering;
-import java.io.StringReader;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
import org.hibernate.sql.ast.util.TreePrinter;
-import org.antlr.runtime.CharStream;
-import org.antlr.runtime.TokenStream;
+import org.hibernate.sql.ast.phase.hql.parse.HQLLexer;
+
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.tree.Tree;
@@ -59,13 +57,13 @@
* @return The translated fragment.
*/
public String render(String fragment) {
- OrderByParserLexer lexer = new OrderByParserLexer( new ANTLRStringStream( fragment ) );
+ HQLLexer lexer = new HQLLexer( new ANTLRStringStream( fragment ) );
OrderByFragmentParser parser = new OrderByFragmentParser( new CommonTokenStream( lexer ), context );
try {
Tree tree = ( Tree ) parser.orderByFragment().getTree();
if ( log.isTraceEnabled() ) {
- TreePrinter printer = new TreePrinter( OrderByParserParser.class );
+ TreePrinter printer = new TreePrinter( OrderByParser.class );
log.trace( printer.renderAsString( tree, "--- {order-by fragment} ---" ) );
}
}
Added: core/branches/antlr3/src/test/java/org/hibernate/sql/ast/ordering/OrderByParserTest.java
===================================================================
--- core/branches/antlr3/src/test/java/org/hibernate/sql/ast/ordering/OrderByParserTest.java (rev 0)
+++ core/branches/antlr3/src/test/java/org/hibernate/sql/ast/ordering/OrderByParserTest.java 2009-04-24 21:05:09 UTC (rev 16437)
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2009, 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.ast.ordering;
+
+import java.util.Collections;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.persister.entity.PropertyMapping;
+import org.hibernate.QueryException;
+import org.hibernate.Hibernate;
+import org.hibernate.HibernateException;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.dialect.function.SQLFunctionRegistry;
+import org.hibernate.dialect.function.SQLFunction;
+import org.hibernate.dialect.function.SQLFunctionTemplate;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.sql.ast.phase.hql.parse.HQLLexer;
+import org.hibernate.sql.ast.util.ASTUtil;
+import org.hibernate.sql.ast.util.TreePrinter;
+import org.hibernate.sql.Template;
+import org.hibernate.type.Type;
+
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.tree.Tree;
+import org.antlr.runtime.tree.CommonTree;
+
+/**
+ * Assertions against the structures generated by various paths of the "order-by" mapping fragment parser.
+ *
+ * @author Steve Ebersole
+ */
+public class OrderByParserTest extends TestCase {
+ public static final PropertyMapping STANDARD_PROPERTY_MAPPING = new PropertyMapping() {
+ public String[] toColumns(String propertyName) throws QueryException, UnsupportedOperationException {
+ if ( "component".equals( propertyName ) ) {
+ return new String[] { "comp_1", "comp_2" };
+ }
+ else if ( "component.prop1".equals( propertyName ) ) {
+ return new String[] { "comp_1" };
+ }
+ else if ( "component.prop2".equals( propertyName ) ) {
+ return new String[] { "comp_2" };
+ }
+ else if ( "property".equals( propertyName ) ) {
+ return new String[] { "prop" };
+ }
+ throw new QueryException( "could not resolve property: " + propertyName );
+ }
+
+ public Type toType(String propertyName) throws QueryException {
+ throw new UnsupportedOperationException( "toType(propertyName) not supported here" );
+ }
+
+ public String[] toColumns(String alias, String propertyName) throws QueryException {
+ throw new UnsupportedOperationException( "toColumns(alias,propertyName) not supported here" );
+ }
+
+ public Type getType() {
+ throw new UnsupportedOperationException( "getType() not supported here" );
+ }
+ };
+
+ public static final ColumnMapper STANDARD_MAPPER = new ColumnMapper() {
+ public String[] map(String reference) {
+ return STANDARD_PROPERTY_MAPPING.toColumns( reference );
+ }
+ };
+
+ public OrderByParserTest() {
+ }
+
+ public OrderByParserTest(String name) {
+ super( name );
+ }
+
+ public void testSQLReferences() {
+ String fragment = "sql asc, sql desc";
+ CommonTree tree = parse( fragment );
+
+ assertTokenType( HQLLexer.ORDER_BY, tree );
+ assertEquals( 2, tree.getChildCount() );
+
+ Tree firstSortSpec = tree.getChild( 0 );
+ assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec );
+ assertEquals( 2, firstSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
+ assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText() );
+ assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
+ assertEquals( "sql", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+ assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
+ assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
+
+ Tree secondSortSpec = tree.getChild( 1 );
+ assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
+ assertEquals( 2, secondSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
+ assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText() );
+ assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
+ assertEquals( "sql", secondSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+ assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
+ assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
+ }
+
+ public void testQuotedSQLReferences() {
+ String fragment = "`sql` asc, `sql` desc";
+ CommonTree tree = parse( fragment );
+
+ assertTokenType( HQLLexer.ORDER_BY, tree.getType() );
+ assertEquals( 2, tree.getChildCount() );
+
+ Tree firstSortSpec = tree.getChild( 0 );
+ assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
+ assertEquals( 2, firstSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
+ assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText() );
+ assertTokenType( HQLLexer.QUOTED_IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
+ assertEquals( "`sql`", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+ assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
+ assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
+
+ Tree secondSortSpec = tree.getChild( 1 );
+ assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
+ assertEquals( 2, secondSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
+ assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText() );
+ assertTokenType( HQLLexer.QUOTED_IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
+ assertEquals( "`sql`", secondSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+ assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
+ assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
+ }
+
+ public void testPropertyReference() {
+ String fragment = "property asc, property desc";
+ CommonTree tree = parse( fragment );
+
+ assertTokenType( HQLLexer.ORDER_BY, tree.getType() );
+ assertEquals( 2, tree.getChildCount() );
+
+ Tree firstSortSpec = tree.getChild( 0 );
+ assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
+ assertEquals( 2, firstSortSpec.getChildCount() );
+ assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
+ assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
+ assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText() );
+ assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
+ assertEquals( "prop", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+ assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
+ assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
+ }
+
+ protected CommonTree parse(String orderByFragment) {
+ final Dialect dialect = new HSQLDialect();
+ final SQLFunction myFunction = new SQLFunctionTemplate( Hibernate.STRING, "myFunction($1)" );
+ final SQLFunctionRegistry functionRegistry = new SQLFunctionRegistry( dialect, Collections.singletonMap( "myFunction", myFunction ) );
+ return parse(
+ orderByFragment,
+ new TranslationContext() {
+ public SessionFactoryImplementor getSessionFactory() {
+ return null;
+ }
+
+ public Dialect getDialect() {
+ return dialect;
+ }
+
+ public SQLFunctionRegistry getSqlFunctionRegistry() {
+ return functionRegistry;
+ }
+
+ public ColumnMapper getColumnMapper() {
+ return STANDARD_MAPPER;
+ }
+ }
+ );
+ }
+
+ private static final TreePrinter TREE_PRINTER = new TreePrinter( HQLLexer.class );
+
+ protected CommonTree parse(String orderByFragment, TranslationContext context) {
+ try {
+ HQLLexer lexer = new HQLLexer( new ANTLRStringStream( orderByFragment ) );
+ OrderByFragmentParser parser = new OrderByFragmentParser( new CommonTokenStream( lexer ), context );
+ CommonTree rtn = parser.orderByFragment().tree;
+ // temp
+ System.out.println(
+ TREE_PRINTER.renderAsString( rtn, "fragment" )
+ );
+ return rtn;
+ }
+ catch ( HibernateException e ) {
+ throw e;
+ }
+ catch ( Throwable t ) {
+ throw new HibernateException( "Unable to parse order-by fragment", t );
+ }
+ }
+
+ private static final Map<Integer,String> tokenNameMap = ( Map<Integer,String> ) ASTUtil.generateTokenNameCache( HQLLexer.class );
+
+ public void assertTokenType(int expected, int actual) {
+ if ( expected != actual ) {
+ throw new AssertionFailedError(
+ "expected:<"+ tokenNameMap.get( expected ) +"> but was:<"+ tokenNameMap.get( actual ) +">"
+ );
+ }
+ }
+
+ public void assertTokenType(int expected, Tree tree) {
+ if ( tree == null ) {
+ throw new AssertionFailedError(
+ "expected:<"+ tokenNameMap.get( expected ) +"> but was:<null>"
+ );
+ }
+ assertTokenType( expected, tree.getType() );
+ }
+}
15 years
Hibernate SVN: r16436 - core/branches/antlr3/src/main/java/org/hibernate/sql/ast/tree.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2009-04-24 11:30:34 -0400 (Fri, 24 Apr 2009)
New Revision: 16436
Modified:
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/tree/Table.java
Log:
added the notion of building a select expression list (per persister/table space)
Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/tree/Table.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/tree/Table.java 2009-04-24 12:21:07 UTC (rev 16435)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/tree/Table.java 2009-04-24 15:30:34 UTC (rev 16436)
@@ -134,6 +134,10 @@
public HibernateTree buildIdentifierColumnReferences();
public HibernateTree buildCompleteColumnReferences();
+
+ public HibernateTree buildIdentifierSelectExpressionList();
+
+ public HibernateTree buildCompleteSelectExpressionList();
}
public static abstract class AbstractTableSpace implements Table.TableSpace {
@@ -243,6 +247,16 @@
// todo : implement
return null;
}
+
+ public HibernateTree buildIdentifierSelectExpressionList() {
+ // todo : implement
+ return null;
+ }
+
+ public HibernateTree buildCompleteSelectExpressionList() {
+ // todo : implement
+ return null;
+ }
}
private static class EntityPersisterSpace extends AbstractPersisterSpace {
@@ -341,6 +355,16 @@
// todo : implement
return null;
}
+
+ public HibernateTree buildIdentifierSelectExpressionList() {
+ // todo : implement
+ return null;
+ }
+
+ public HibernateTree buildCompleteSelectExpressionList() {
+ // todo : implement
+ return null;
+ }
}
public static class CollectionPersisterSpace extends AbstractPersisterSpace {
15 years
Hibernate SVN: r16435 - in annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations: join and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: jcosta(a)redhat.com
Date: 2009-04-24 08:21:07 -0400 (Fri, 24 Apr 2009)
New Revision: 16435
Modified:
annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/EntityTest.java
annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/Sky.java
annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/join/Cat.java
annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/join/JoinTest.java
Log:
ANN-822 - JBPAPP-1894 - Backported fix from trunk. For branch v3_3_1_GA_CP
Modified: annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/EntityTest.java
===================================================================
--- annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/EntityTest.java 2009-04-24 10:11:25 UTC (rev 16434)
+++ annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/EntityTest.java 2009-04-24 12:21:07 UTC (rev 16435)
@@ -243,6 +243,8 @@
sky.id = new Long( 1 );
sky.color = "black";
Sky.area = "Paris";
+ sky.day = "23";
+ sky.month = "1";
s.save( sky );
tx.commit();
s.close();
Modified: annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/Sky.java
===================================================================
--- annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/Sky.java 2009-04-24 10:11:25 UTC (rev 16434)
+++ annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/Sky.java 2009-04-24 12:21:07 UTC (rev 16435)
@@ -18,10 +18,11 @@
public class Sky implements Serializable {
@Id
protected Long id;
- @Column(unique = true, columnDefinition = "varchar(250)")
+ @Column(unique = true, columnDefinition = "varchar(250)", nullable = false)
protected String color;
+ @Column(nullable = false)
protected String day;
- @Column(name = "MONTH")
+ @Column(name = "MONTH", nullable = false)
protected String month;
static protected String area;
}
Modified: annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/join/Cat.java
===================================================================
--- annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/join/Cat.java 2009-04-24 10:11:25 UTC (rev 16434)
+++ annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/join/Cat.java 2009-04-24 12:21:07 UTC (rev 16435)
@@ -83,7 +83,7 @@
return storyPart1;
}
- @Column(table = "Cat2")
+ @Column(table = "Cat2", nullable = false)
public String getStoryPart2() {
return storyPart2;
}
Modified: annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/join/JoinTest.java
===================================================================
--- annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/join/JoinTest.java 2009-04-24 10:11:25 UTC (rev 16434)
+++ annotations/branches/v3_3_1_GA_CP/src/test/org/hibernate/test/annotations/join/JoinTest.java 2009-04-24 12:21:07 UTC (rev 16435)
@@ -99,6 +99,7 @@
Life life = new Life();
Cat cat = new Cat();
cat.setName( "kitty" );
+ cat.setStoryPart2( "and the story continues" );
life.duration = 15;
life.fullDescription = "Long long description";
life.owner = cat;
15 years
Hibernate SVN: r16434 - validator/trunk.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-04-24 06:11:25 -0400 (Fri, 24 Apr 2009)
New Revision: 16434
Modified:
validator/trunk/pom.xml
Log:
Modified: validator/trunk/pom.xml
===================================================================
--- validator/trunk/pom.xml 2009-04-24 10:06:23 UTC (rev 16433)
+++ validator/trunk/pom.xml 2009-04-24 10:11:25 UTC (rev 16434)
@@ -139,10 +139,6 @@
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
- <!--
- During release:perform, enable the "release" profile
- -->
- <releaseProfiles>release</releaseProfiles>
<goals>package site assembly:assembly</goals>
</configuration>
</plugin>
15 years