Least-effort fix for HHH-2692
Conflicts: hibernate-core/src/main/java/org/hibernate/hql/ast/HqlSqlWalker.java hibernate-core/src/main/java/org/hibernate/hql/ast/tree/IntoClause.java hibernate-core/src/main/java/org/hibernate/hql/ast/tree/SelectExpressionList.java hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java
This commit is contained in:
parent
51deee1e66
commit
9304c2b3e9
|
@ -409,6 +409,7 @@ selectExpr
|
|||
| collectionFunction // elements() or indices()
|
||||
| literal
|
||||
| arithmeticExpr
|
||||
| parameter
|
||||
| query
|
||||
;
|
||||
|
||||
|
|
|
@ -246,7 +246,7 @@ selectExpr
|
|||
| aggregate
|
||||
| c:constant { out(c); }
|
||||
| arithmeticExpr
|
||||
| param:PARAM { out(param); }
|
||||
| parameter
|
||||
| sn:SQL_NODE { out(sn); }
|
||||
| { out("("); } selectStatement { out(")"); }
|
||||
;
|
||||
|
|
|
@ -36,12 +36,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import antlr.ASTFactory;
|
||||
import antlr.RecognitionException;
|
||||
import antlr.SemanticException;
|
||||
import antlr.collections.AST;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.engine.internal.JoinSequence;
|
||||
|
@ -104,6 +98,12 @@ import org.hibernate.type.DbTimestampType;
|
|||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.VersionType;
|
||||
import org.hibernate.usertype.UserVersionType;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import antlr.ASTFactory;
|
||||
import antlr.RecognitionException;
|
||||
import antlr.SemanticException;
|
||||
import antlr.collections.AST;
|
||||
|
||||
/**
|
||||
* Implements methods used by the HQL->SQL tree transform grammar (a.k.a. the second phase).
|
||||
|
@ -775,6 +775,20 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
|||
}
|
||||
}
|
||||
|
||||
if ( sessionFactoryHelper.getFactory().getDialect().supportsParametersInInsertSelect() ) {
|
||||
AST child = selectClause.getFirstChild();
|
||||
int i = 0;
|
||||
while(child != null) {
|
||||
if(child instanceof ParameterNode) {
|
||||
// infer the parameter type from the type listed in the INSERT INTO clause
|
||||
((ParameterNode)child).setExpectedType(insertStatement.getIntoClause()
|
||||
.getInsertionTypes()[selectClause.getParameterPositions().get(i)]);
|
||||
i++;
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
final boolean includeVersionProperty = persister.isVersioned() &&
|
||||
!insertStatement.getIntoClause().isExplicitVersionInsertion() &&
|
||||
persister.isVersionPropertyInsertable();
|
||||
|
|
|
@ -116,12 +116,16 @@ public class IntoClause extends HqlSqlWalkerNode implements DisplayableNode {
|
|||
|
||||
public void validateTypes(SelectClause selectClause) throws QueryException {
|
||||
Type[] selectTypes = selectClause.getQueryReturnTypes();
|
||||
if ( selectTypes.length != types.length ) {
|
||||
if ( selectTypes.length + selectClause.getTotalParameterCount() != types.length ) {
|
||||
throw new QueryException( "number of select types did not match those for insert" );
|
||||
}
|
||||
|
||||
int parameterCount = 0;
|
||||
for ( int i = 0; i < types.length; i++ ) {
|
||||
if ( !areCompatible( types[i], selectTypes[i] ) ) {
|
||||
if( selectClause.getParameterPositions().contains(i) ) {
|
||||
parameterCount++;
|
||||
}
|
||||
else if ( !areCompatible( types[i], selectTypes[i - parameterCount] ) ) {
|
||||
throw new QueryException(
|
||||
"insertion type [" + types[i] + "] and selection type [" +
|
||||
selectTypes[i] + "] at position " + i + " are not compatible"
|
||||
|
|
|
@ -24,18 +24,22 @@
|
|||
*/
|
||||
package org.hibernate.hql.internal.ast.tree;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import antlr.collections.AST;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.hql.internal.antlr.SqlTokenTypes;
|
||||
import org.hibernate.hql.internal.ast.util.ASTPrinter;
|
||||
|
||||
import antlr.collections.AST;
|
||||
|
||||
/**
|
||||
* Common behavior - a node that contains a list of select expressions.
|
||||
*
|
||||
* @author josh
|
||||
*/
|
||||
public abstract class SelectExpressionList extends HqlSqlWalkerNode {
|
||||
|
||||
private List<Integer> parameterPositions = new ArrayList<Integer>();
|
||||
|
||||
/**
|
||||
* Returns an array of SelectExpressions gathered from the children of the given parent AST node.
|
||||
*
|
||||
|
@ -47,17 +51,40 @@ public abstract class SelectExpressionList extends HqlSqlWalkerNode {
|
|||
AST firstChild = getFirstSelectExpression();
|
||||
AST parent = this;
|
||||
ArrayList list = new ArrayList( parent.getNumberOfChildren() );
|
||||
int p = 0;
|
||||
for ( AST n = firstChild; n != null; n = n.getNextSibling() ) {
|
||||
if ( n instanceof SelectExpression ) {
|
||||
list.add( n );
|
||||
}
|
||||
else if( n instanceof ParameterNode ) {
|
||||
parameterPositions.add(p);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException( "Unexpected AST: " + n.getClass().getName() + " " + new ASTPrinter( SqlTokenTypes.class ).showAsString( n, "" ) );
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return ( SelectExpression[] ) list.toArray( new SelectExpression[list.size()] );
|
||||
}
|
||||
|
||||
/**
|
||||
* The total number of parameter projections of this expression.
|
||||
*
|
||||
* @return The number of parameters in this select clause.
|
||||
*/
|
||||
public int getTotalParameterCount() {
|
||||
return parameterPositions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of parameters within the list of select expressions of this clause
|
||||
*
|
||||
* @return a list of positions representing the mapping from order of occurence to position
|
||||
*/
|
||||
public List<Integer> getParameterPositions() {
|
||||
return parameterPositions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first select expression node that should be considered when building the array of select
|
||||
* expressions.
|
||||
|
|
|
@ -209,6 +209,30 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase {
|
|||
data.cleanup();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleInsertWithNamedParam() {
|
||||
TestData data = new TestData();
|
||||
data.prepare();
|
||||
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
||||
org.hibernate.Query q = s.createQuery( "insert into Pickup (id, owner, vin) select id, :owner, vin from Car" );
|
||||
q.setParameter("owner", "owner");
|
||||
|
||||
q.executeUpdate();
|
||||
|
||||
t.commit();
|
||||
t = s.beginTransaction();
|
||||
|
||||
s.createQuery( "delete Vehicle" ).executeUpdate();
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
data.cleanup();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleNativeSQLInsert() {
|
||||
TestData data = new TestData();
|
||||
|
|
Loading…
Reference in New Issue