[hibernate-commits] Hibernate SVN: r18508 - in core/trunk: core/src/main/java/org/hibernate/hql/ast and 4 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Mon Jan 11 17:55:37 EST 2010
Author: steve.ebersole at jboss.com
Date: 2010-01-11 17:55:36 -0500 (Mon, 11 Jan 2010)
New Revision: 18508
Modified:
core/trunk/core/src/main/antlr/hql-sql.g
core/trunk/core/src/main/antlr/hql.g
core/trunk/core/src/main/antlr/sql-gen.g
core/trunk/core/src/main/java/org/hibernate/hql/ast/SqlASTFactory.java
core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/LiteralNode.java
core/trunk/core/src/main/java/org/hibernate/hql/ast/util/LiteralProcessor.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ValueHandlerFactory.java
core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java
Log:
HHH-4780 - Allow BigDecimal and BigInteger to be specified as numeric literal types
Modified: core/trunk/core/src/main/antlr/hql-sql.g
===================================================================
--- core/trunk/core/src/main/antlr/hql-sql.g 2010-01-11 20:27:12 UTC (rev 18507)
+++ core/trunk/core/src/main/antlr/hql-sql.g 2010-01-11 22:55:36 UTC (rev 18508)
@@ -598,6 +598,8 @@
| NUM_LONG { processNumericLiteral( #literal ); }
| NUM_FLOAT { processNumericLiteral( #literal ); }
| NUM_DOUBLE { processNumericLiteral( #literal ); }
+ | NUM_BIG_INTEGER { processNumericLiteral( #literal ); }
+ | NUM_BIG_DECIMAL { processNumericLiteral( #literal ); }
| QUOTED_STRING
;
Modified: core/trunk/core/src/main/antlr/hql.g
===================================================================
--- core/trunk/core/src/main/antlr/hql.g 2010-01-11 20:27:12 UTC (rev 18507)
+++ core/trunk/core/src/main/antlr/hql.g 2010-01-11 22:55:36 UTC (rev 18508)
@@ -133,6 +133,8 @@
NUM_DOUBLE;
NUM_FLOAT;
NUM_LONG;
+ NUM_BIG_INTEGER;
+ NUM_BIG_DECIMAL;
JAVA_CONSTANT;
}
@@ -693,6 +695,8 @@
| NUM_FLOAT
| NUM_LONG
| NUM_DOUBLE
+ | NUM_BIG_INTEGER
+ | NUM_BIG_DECIMAL
| QUOTED_STRING
| NULL
| TRUE
@@ -821,12 +825,13 @@
: '.' {_ttype = DOT;}
( ('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})?
{
- if (t != null && t.getText().toUpperCase().indexOf('F')>=0)
- {
+ if ( t != null && t.getText().toUpperCase().indexOf("BD")>=0) {
+ _ttype = NUM_BIG_DECIMAL;
+ }
+ else if (t != null && t.getText().toUpperCase().indexOf('F')>=0) {
_ttype = NUM_FLOAT;
}
- else
- {
+ else {
_ttype = NUM_DOUBLE; // assume double
}
}
@@ -847,6 +852,7 @@
| ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal
)
( ('l') { _ttype = NUM_LONG; }
+ | ('b''i') { _ttype = NUM_BIG_INTEGER; }
// only check to see if it's a float if looks like decimal so far
| {isDecimal}?
@@ -855,12 +861,13 @@
| f4:FLOAT_SUFFIX {t=f4;}
)
{
- if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0)
- {
+ if ( t != null && t.getText().toUpperCase().indexOf("BD")>=0) {
+ _ttype = NUM_BIG_DECIMAL;
+ }
+ else if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) {
_ttype = NUM_FLOAT;
}
- else
- {
+ else {
_ttype = NUM_DOUBLE; // assume double
}
}
@@ -881,6 +888,6 @@
protected
FLOAT_SUFFIX
- : 'f'|'d'
+ : 'f'|'d'|'b''d'
;
Modified: core/trunk/core/src/main/antlr/sql-gen.g
===================================================================
--- core/trunk/core/src/main/antlr/sql-gen.g 2010-01-11 20:27:12 UTC (rev 18507)
+++ core/trunk/core/src/main/antlr/sql-gen.g 2010-01-11 22:55:36 UTC (rev 18508)
@@ -353,6 +353,8 @@
| NUM_FLOAT
| NUM_INT
| NUM_LONG
+ | NUM_BIG_INTEGER
+ | NUM_BIG_DECIMAL
| QUOTED_STRING
| CONSTANT
| JAVA_CONSTANT
Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/SqlASTFactory.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/SqlASTFactory.java 2010-01-11 20:27:12 UTC (rev 18507)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/SqlASTFactory.java 2010-01-11 22:55:36 UTC (rev 18508)
@@ -145,6 +145,8 @@
case NUM_FLOAT:
case NUM_LONG:
case NUM_DOUBLE:
+ case NUM_BIG_INTEGER:
+ case NUM_BIG_DECIMAL:
case QUOTED_STRING:
return LiteralNode.class;
case TRUE:
Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/LiteralNode.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/LiteralNode.java 2010-01-11 20:27:12 UTC (rev 18507)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/LiteralNode.java 2010-01-11 22:55:36 UTC (rev 18508)
@@ -22,7 +22,6 @@
* Boston, MA 02110-1301 USA
*
*/
-
package org.hibernate.hql.ast.tree;
import org.hibernate.Hibernate;
@@ -53,6 +52,10 @@
return Hibernate.LONG;
case NUM_DOUBLE:
return Hibernate.DOUBLE;
+ case NUM_BIG_INTEGER:
+ return Hibernate.BIG_INTEGER;
+ case NUM_BIG_DECIMAL:
+ return Hibernate.BIG_DECIMAL;
case QUOTED_STRING:
return Hibernate.STRING;
case TRUE:
Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/util/LiteralProcessor.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/util/LiteralProcessor.java 2010-01-11 20:27:12 UTC (rev 18507)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/util/LiteralProcessor.java 2010-01-11 22:55:36 UTC (rev 18508)
@@ -50,6 +50,7 @@
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
+import java.math.BigInteger;
import java.text.DecimalFormat;
/**
@@ -229,10 +230,14 @@
}
public void processNumeric(AST literal) {
- if ( literal.getType() == NUM_INT || literal.getType() == NUM_LONG ) {
+ if ( literal.getType() == NUM_INT
+ || literal.getType() == NUM_LONG
+ || literal.getType() == NUM_BIG_INTEGER ) {
literal.setText( determineIntegerRepresentation( literal.getText(), literal.getType() ) );
}
- else if ( literal.getType() == NUM_FLOAT || literal.getType() == NUM_DOUBLE ) {
+ else if ( literal.getType() == NUM_FLOAT
+ || literal.getType() == NUM_DOUBLE
+ || literal.getType() == NUM_BIG_DECIMAL ) {
literal.setText( determineDecimalRepresentation( literal.getText(), literal.getType() ) );
}
else {
@@ -250,11 +255,21 @@
log.trace( "could not format incoming text [" + text + "] as a NUM_INT; assuming numeric overflow and attempting as NUM_LONG" );
}
}
- String literalValue = text;
- if ( literalValue.endsWith( "l" ) || literalValue.endsWith( "L" ) ) {
- literalValue = literalValue.substring( 0, literalValue.length() - 1 );
+ else if ( type == NUM_LONG ) {
+ String literalValue = text;
+ if ( literalValue.endsWith( "l" ) || literalValue.endsWith( "L" ) ) {
+ literalValue = literalValue.substring( 0, literalValue.length() - 1 );
+ }
+ return Long.valueOf( literalValue ).toString();
}
- return Long.valueOf( literalValue ).toString();
+ else if ( type == NUM_BIG_INTEGER ) {
+ String literalValue = text;
+ if ( literalValue.endsWith( "bi" ) || literalValue.endsWith( "BI" ) ) {
+ literalValue = literalValue.substring( 0, literalValue.length() - 2 );
+ }
+ return new BigInteger( literalValue ).toString();
+ }
+ throw new HibernateException( "Unknown literal type to parse as integer" );
}
catch( Throwable t ) {
throw new HibernateException( "Could not parse literal [" + text + "] as integer", t );
@@ -273,6 +288,11 @@
literalValue = literalValue.substring( 0, literalValue.length() - 1 );
}
}
+ else if ( type == NUM_BIG_DECIMAL ) {
+ if ( literalValue.endsWith( "bd" ) || literalValue.endsWith( "BD" ) ) {
+ literalValue = literalValue.substring( 0, literalValue.length() - 2 );
+ }
+ }
BigDecimal number = null;
try {
@@ -285,6 +305,7 @@
return formatters[ DECIMAL_LITERAL_FORMAT ].format( number );
}
+
private static interface DecimalFormatter {
String format(BigDecimal number);
}
Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ValueHandlerFactory.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ValueHandlerFactory.java 2010-01-11 20:27:12 UTC (rev 18507)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ValueHandlerFactory.java 2010-01-11 22:55:36 UTC (rev 18508)
@@ -217,6 +217,11 @@
}
throw unknownConversion( value, BigInteger.class );
}
+
+ @Override
+ public String render(BigInteger value) {
+ return "cast( " + value.toString() + " as BigInteger )";
+ }
}
public static class BigDecimalValueHandler extends BaseValueHandler<BigDecimal> implements Serializable {
@@ -236,6 +241,11 @@
}
throw unknownConversion( value, BigDecimal.class );
}
+
+ @Override
+ public String render(BigDecimal value) {
+ return "cast( " + value.toString() + " as BigDecimal )";
+ }
}
public static class StringValueHandler extends BaseValueHandler<String> implements Serializable {
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java 2010-01-11 20:27:12 UTC (rev 18507)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java 2010-01-11 22:55:36 UTC (rev 18508)
@@ -2,6 +2,7 @@
package org.hibernate.test.hql;
import java.math.BigDecimal;
+import java.math.BigInteger;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
@@ -1195,14 +1196,129 @@
a.setBodyWeight(12.4f);
a.setDescription("an animal");
s.persist(a);
- Integer bw = (Integer) s.createQuery("select cast(bodyWeight as integer) from Animal").uniqueResult();
- bw = (Integer) s.createQuery("select cast(a.bodyWeight as integer) from Animal a").uniqueResult();
- bw.toString();
+ Object bodyWeight = s.createQuery("select cast(bodyWeight as integer) from Animal").uniqueResult();
+ assertTrue( Integer.class.isInstance( bodyWeight ) );
+ assertEquals( 12, bodyWeight );
+ bodyWeight = s.createQuery("select cast(bodyWeight as big_decimal) from Animal").uniqueResult();
+ assertTrue( BigDecimal.class.isInstance( bodyWeight ) );
+ assertEquals( BigDecimal.valueOf( a.getBodyWeight() ), bodyWeight );
+ Object literal = s.createQuery("select cast(10000000 as big_integer) from Animal").uniqueResult();
+ assertTrue( BigInteger.class.isInstance( literal ) );
+ assertEquals( BigInteger.valueOf( 10000000 ), literal );
s.delete(a);
t.commit();
s.close();
}
+ /**
+ * Test the numeric expression rules specified in section 4.8.6 of the JPA 2 specification
+ */
+ public void testNumericExpressionReturnTypes() {
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ Animal a = new Animal();
+ a.setBodyWeight(12.4f);
+ a.setDescription("an animal");
+ s.persist(a);
+
+ Object result;
+
+ // addition ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ result = s.createQuery( "select 1 + 1 from Animal as a" ).uniqueResult();
+ assertTrue( "int + int", Integer.class.isInstance( result ) );
+ assertEquals( 2, result );
+
+ result = s.createQuery( "select 1 + 1L from Animal a" ).uniqueResult();
+ assertTrue( "int + long", Long.class.isInstance( result ) );
+ assertEquals( Long.valueOf( 2 ), result );
+
+ result = s.createQuery( "select 1 + 1BI from Animal a" ).uniqueResult();
+ assertTrue( "int + BigInteger", BigInteger.class.isInstance( result ) );
+ assertEquals( BigInteger.valueOf( 2 ), result );
+
+ result = s.createQuery( "select 1 + 1F from Animal a" ).uniqueResult();
+ assertTrue( "int + float", Float.class.isInstance( result ) );
+ assertEquals( Float.valueOf( 2 ), result );
+
+ result = s.createQuery( "select 1 + 1D from Animal a" ).uniqueResult();
+ assertTrue( "int + double", Double.class.isInstance( result ) );
+ assertEquals( Double.valueOf( 2 ), result );
+
+ result = s.createQuery( "select 1 + 1BD from Animal a" ).uniqueResult();
+ assertTrue( "int + BigDecimal", BigDecimal.class.isInstance( result ) );
+ assertEquals( BigDecimal.valueOf( 2 ), result );
+
+ result = s.createQuery( "select 1F + 1D from Animal a" ).uniqueResult();
+ assertTrue( "float + double", Double.class.isInstance( result ) );
+ assertEquals( Double.valueOf( 2 ), result );
+
+ result = s.createQuery( "select 1F + 1BD from Animal a" ).uniqueResult();
+ assertTrue( "float + BigDecimal", Float.class.isInstance( result ) );
+ assertEquals( Float.valueOf( 2 ), result );
+
+ // subtraction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ result = s.createQuery( "select 1 - 1 from Animal as a" ).uniqueResult();
+ assertTrue( "int - int", Integer.class.isInstance( result ) );
+ assertEquals( 0, result );
+
+ result = s.createQuery( "select 1 - 1L from Animal a" ).uniqueResult();
+ assertTrue( "int - long", Long.class.isInstance( result ) );
+ assertEquals( Long.valueOf( 0 ), result );
+
+ result = s.createQuery( "select 1 - 1BI from Animal a" ).uniqueResult();
+ assertTrue( "int - BigInteger", BigInteger.class.isInstance( result ) );
+ assertEquals( BigInteger.valueOf( 0 ), result );
+
+ result = s.createQuery( "select 1 - 1F from Animal a" ).uniqueResult();
+ assertTrue( "int - float", Float.class.isInstance( result ) );
+ assertEquals( Float.valueOf( 0 ), result );
+
+ result = s.createQuery( "select 1 - 1D from Animal a" ).uniqueResult();
+ assertTrue( "int - double", Double.class.isInstance( result ) );
+ assertEquals( Double.valueOf( 0 ), result );
+
+ result = s.createQuery( "select 1 - 1BD from Animal a" ).uniqueResult();
+ assertTrue( "int - BigDecimal", BigDecimal.class.isInstance( result ) );
+ assertEquals( BigDecimal.valueOf( 0 ), result );
+
+ result = s.createQuery( "select 1F - 1D from Animal a" ).uniqueResult();
+ assertTrue( "float - double", Double.class.isInstance( result ) );
+ assertEquals( Double.valueOf( 0 ), result );
+
+ result = s.createQuery( "select 1F - 1BD from Animal a" ).uniqueResult();
+ assertTrue( "float - BigDecimal", Float.class.isInstance( result ) );
+ assertEquals( Float.valueOf( 0 ), result );
+
+ // multiplication ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ result = s.createQuery( "select 1 * 1 from Animal as a" ).uniqueResult();
+ assertTrue( "int * int", Integer.class.isInstance( result ) );
+ assertEquals( 1, result );
+
+ result = s.createQuery( "select 1 * 1L from Animal a" ).uniqueResult();
+ assertTrue( "int * long", Long.class.isInstance( result ) );
+ assertEquals( Long.valueOf( 1 ), result );
+
+ result = s.createQuery( "select 1 * 1BI from Animal a" ).uniqueResult();
+ assertTrue( "int * BigInteger", BigInteger.class.isInstance( result ) );
+ assertEquals( BigInteger.valueOf( 1 ), result );
+
+ result = s.createQuery( "select 1 * 1F from Animal a" ).uniqueResult();
+ assertTrue( "int * float", Float.class.isInstance( result ) );
+ assertEquals( Float.valueOf( 1 ), result );
+
+ result = s.createQuery( "select 1 * 1D from Animal a" ).uniqueResult();
+ assertTrue( "int * double", Double.class.isInstance( result ) );
+ assertEquals( Double.valueOf( 1 ), result );
+
+ result = s.createQuery( "select 1 * 1BD from Animal a" ).uniqueResult();
+ assertTrue( "int * BigDecimal", BigDecimal.class.isInstance( result ) );
+ assertEquals( BigDecimal.valueOf( 1 ), result );
+
+ s.delete(a);
+ t.commit();
+ s.close();
+ }
+
public void testAliases() {
Session s = openSession();
Transaction t = s.beginTransaction();
More information about the hibernate-commits
mailing list