HHH-10861 - Fix nullLiteral in select expression

This commit is contained in:
Andrea Boriero 2016-06-20 15:16:52 +02:00
parent e71af130f0
commit 597183a3b9
6 changed files with 62 additions and 7 deletions

View File

@ -689,7 +689,7 @@ functionCall
constant constant
: literal : literal
| NULL | NULL
| TRUE { processBoolean(#constant); } | TRUE { processBoolean(#constant); }
| FALSE { processBoolean(#constant); } | FALSE { processBoolean(#constant); }
| JAVA_CONSTANT | JAVA_CONSTANT
; ;

View File

@ -15,6 +15,7 @@ import org.hibernate.hql.internal.ast.tree.BinaryArithmeticOperatorNode;
import org.hibernate.hql.internal.ast.tree.BinaryLogicOperatorNode; import org.hibernate.hql.internal.ast.tree.BinaryLogicOperatorNode;
import org.hibernate.hql.internal.ast.tree.BooleanLiteralNode; import org.hibernate.hql.internal.ast.tree.BooleanLiteralNode;
import org.hibernate.hql.internal.ast.tree.CastFunctionNode; import org.hibernate.hql.internal.ast.tree.CastFunctionNode;
import org.hibernate.hql.internal.ast.tree.NullNode;
import org.hibernate.hql.internal.ast.tree.SearchedCaseNode; import org.hibernate.hql.internal.ast.tree.SearchedCaseNode;
import org.hibernate.hql.internal.ast.tree.SimpleCaseNode; import org.hibernate.hql.internal.ast.tree.SimpleCaseNode;
import org.hibernate.hql.internal.ast.tree.CollectionFunction; import org.hibernate.hql.internal.ast.tree.CollectionFunction;
@ -192,6 +193,9 @@ public class SqlASTFactory extends ASTFactory implements HqlSqlTokenTypes {
case ENTRY: { case ENTRY: {
return MapEntryNode.class; return MapEntryNode.class;
} }
case NULL : {
return NullNode.class;
}
default: default:
return SqlNode.class; return SqlNode.class;
} }

View File

@ -0,0 +1,38 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.hql.internal.ast.tree;
import antlr.SemanticException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.hql.internal.ast.util.ColumnHelper;
import org.hibernate.type.Type;
/**
* @author Andrea Boriero
*/
public class NullNode extends AbstractSelectExpression {
public Type getDataType() {
return null;
}
@Override
public void setScalarColumnText(int i) throws SemanticException {
ColumnHelper.generateSingleScalarColumn( this, i );
}
public Object getValue() {
return null;
}
@Override
@SuppressWarnings({"unchecked"})
public String getRenderText(SessionFactoryImplementor sessionFactory) {
return "null";
}
}

View File

@ -191,6 +191,10 @@ public class LiteralProcessor implements HqlSqlTokenTypes {
} }
} }
public void processNull(AST constant) {
constant.setText( "null" );
}
private void processLiteral(AST constant) { private void processLiteral(AST constant) {
String replacement = (String) walker.getTokenReplacements().get( constant.getText() ); String replacement = (String) walker.getTokenReplacements().get( constant.getText() );
if ( replacement != null ) { if ( replacement != null ) {

View File

@ -301,12 +301,14 @@ public final class ReflectHelper {
*/ */
public static Constructor getConstructor(Class clazz, Type[] types) throws PropertyNotFoundException { public static Constructor getConstructor(Class clazz, Type[] types) throws PropertyNotFoundException {
final Constructor[] candidates = clazz.getConstructors(); final Constructor[] candidates = clazz.getConstructors();
for ( final Constructor constructor : candidates ) { Constructor constructor = null;
final Class[] params = constructor.getParameterTypes(); int numberOfMatchingConstructors = 0;
for ( final Constructor candidate : candidates ) {
final Class[] params = candidate.getParameterTypes();
if ( params.length == types.length ) { if ( params.length == types.length ) {
boolean found = true; boolean found = true;
for ( int j = 0; j < params.length; j++ ) { for ( int j = 0; j < params.length; j++ ) {
final boolean ok = params[j].isAssignableFrom( types[j].getReturnedClass() ) || ( final boolean ok = types[j] == null || params[j].isAssignableFrom( types[j].getReturnedClass() ) || (
types[j] instanceof PrimitiveType && types[j] instanceof PrimitiveType &&
params[j] == ( (PrimitiveType) types[j] ).getPrimitiveClass() params[j] == ( (PrimitiveType) types[j] ).getPrimitiveClass()
); );
@ -316,12 +318,18 @@ public final class ReflectHelper {
} }
} }
if ( found ) { if ( found ) {
constructor.setAccessible( true ); numberOfMatchingConstructors ++;
return constructor; candidate.setAccessible( true );
constructor = candidate;
} }
} }
} }
if ( numberOfMatchingConstructors == 1 ) {
return constructor;
}
throw new PropertyNotFoundException( "no appropriate constructor in class: " + clazz.getName() ); throw new PropertyNotFoundException( "no appropriate constructor in class: " + clazz.getName() );
} }
public static Method getMethod(Class clazz, Method method) { public static Method getMethod(Class clazz, Method method) {

View File

@ -11,6 +11,7 @@ import java.io.Serializable;
import org.hibernate.query.criteria.internal.CriteriaBuilderImpl; import org.hibernate.query.criteria.internal.CriteriaBuilderImpl;
import org.hibernate.query.criteria.internal.ParameterRegistry; import org.hibernate.query.criteria.internal.ParameterRegistry;
import org.hibernate.query.criteria.internal.compile.RenderingContext; import org.hibernate.query.criteria.internal.compile.RenderingContext;
import org.hibernate.query.criteria.internal.expression.function.CastFunction;
/** /**
* Represents a <tt>NULL</tt>literal expression. * Represents a <tt>NULL</tt>literal expression.
@ -27,7 +28,7 @@ public class NullLiteralExpression<T> extends ExpressionImpl<T> implements Seria
} }
public String render(RenderingContext renderingContext) { public String render(RenderingContext renderingContext) {
return "null"; return CastFunction.CAST_NAME + "( null as " + renderingContext.getCastType( getJavaType() ) + ')';
} }
public String renderProjection(RenderingContext renderingContext) { public String renderProjection(RenderingContext renderingContext) {