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

@ -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.BooleanLiteralNode;
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.SimpleCaseNode;
import org.hibernate.hql.internal.ast.tree.CollectionFunction;
@ -192,6 +193,9 @@ public class SqlASTFactory extends ASTFactory implements HqlSqlTokenTypes {
case ENTRY: {
return MapEntryNode.class;
}
case NULL : {
return NullNode.class;
}
default:
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) {
String replacement = (String) walker.getTokenReplacements().get( constant.getText() );
if ( replacement != null ) {

View File

@ -301,12 +301,14 @@ public final class ReflectHelper {
*/
public static Constructor getConstructor(Class clazz, Type[] types) throws PropertyNotFoundException {
final Constructor[] candidates = clazz.getConstructors();
for ( final Constructor constructor : candidates ) {
final Class[] params = constructor.getParameterTypes();
Constructor constructor = null;
int numberOfMatchingConstructors = 0;
for ( final Constructor candidate : candidates ) {
final Class[] params = candidate.getParameterTypes();
if ( params.length == types.length ) {
boolean found = true;
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 &&
params[j] == ( (PrimitiveType) types[j] ).getPrimitiveClass()
);
@ -316,12 +318,18 @@ public final class ReflectHelper {
}
}
if ( found ) {
constructor.setAccessible( true );
return constructor;
numberOfMatchingConstructors ++;
candidate.setAccessible( true );
constructor = candidate;
}
}
}
if ( numberOfMatchingConstructors == 1 ) {
return constructor;
}
throw new PropertyNotFoundException( "no appropriate constructor in class: " + clazz.getName() );
}
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.ParameterRegistry;
import org.hibernate.query.criteria.internal.compile.RenderingContext;
import org.hibernate.query.criteria.internal.expression.function.CastFunction;
/**
* 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) {
return "null";
return CastFunction.CAST_NAME + "( null as " + renderingContext.getCastType( getJavaType() ) + ')';
}
public String renderProjection(RenderingContext renderingContext) {