HHH-2692 Handling subqueries in INSERT...SELECT, disallowing use of
:parameters in SELECT if not in INSERT...SELECT, additional test cases Conflicts: hibernate-core/src/main/java/org/hibernate/hql/ast/tree/SelectClause.java hibernate-core/src/test/java/org/hibernate/test/hql/BulkManipulationTest.java
This commit is contained in:
parent
6ad0d4cfbe
commit
f1e4bfbffd
|
@ -26,16 +26,17 @@ import java.util.ArrayList;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import antlr.SemanticException;
|
||||
import antlr.collections.AST;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
|
||||
import org.hibernate.hql.internal.antlr.SqlTokenTypes;
|
||||
import org.hibernate.hql.internal.ast.util.ASTAppender;
|
||||
import org.hibernate.hql.internal.ast.util.ASTIterator;
|
||||
import org.hibernate.hql.internal.ast.util.ASTPrinter;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import antlr.SemanticException;
|
||||
import antlr.collections.AST;
|
||||
|
||||
/**
|
||||
* Represents the list of expressions in a SELECT clause.
|
||||
*
|
||||
|
@ -139,6 +140,11 @@ public class SelectClause extends SelectExpressionList {
|
|||
// changes the AST!!!
|
||||
SelectExpression[] selectExpressions = collectSelectExpressions();
|
||||
|
||||
// we only support parameters in select in the case of INSERT...SELECT statements
|
||||
if (getParameterPositions().size() > 0 && getWalker().getStatementType() != HqlSqlTokenTypes.INSERT) {
|
||||
throw new QueryException("Parameters are only supported in SELECT clauses when used as part of a INSERT INTO DML statement");
|
||||
}
|
||||
|
||||
for ( int i = 0; i < selectExpressions.length; i++ ) {
|
||||
SelectExpression selectExpression = selectExpressions[i];
|
||||
|
||||
|
@ -148,6 +154,17 @@ public class SelectClause extends SelectExpressionList {
|
|||
scalarSelect = true;
|
||||
}
|
||||
else {
|
||||
// we have no choice but to do this check here
|
||||
// this is not very elegant but the "right way" would most likely involve a bigger rewrite so as to
|
||||
// treat ParameterNodes in select clauses as SelectExpressions
|
||||
boolean inSubquery = selectExpression instanceof QueryNode && ((QueryNode) selectExpression).getFromClause().getParentFromClause() != null;
|
||||
if (getWalker().getStatementType() == HqlSqlTokenTypes.INSERT && inSubquery) {
|
||||
// we do not support parameters for subqueries in INSERT...SELECT
|
||||
if (((QueryNode) selectExpression).getSelectClause().getParameterPositions().size() > 0) {
|
||||
throw new QueryException("Use of parameters in subqueries of INSERT INTO DML statements is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
Type type = selectExpression.getDataType();
|
||||
if ( type == null ) {
|
||||
throw new IllegalStateException( "No data type for node: " + selectExpression.getClass().getName() + " "
|
||||
|
|
|
@ -209,6 +209,19 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase {
|
|||
data.cleanup();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectWithNamedParamProjection() {
|
||||
Session s = openSession();
|
||||
try {
|
||||
s.createQuery("select :someParameter, id from Car");
|
||||
fail("Should throw an unsupported exception");
|
||||
} catch(QueryException q) {
|
||||
// allright
|
||||
} finally {
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleInsertWithNamedParam() {
|
||||
TestData data = new TestData();
|
||||
|
@ -233,6 +246,67 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase {
|
|||
data.cleanup();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertWithMultipleNamedParams() {
|
||||
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("id", 5l);
|
||||
q.setParameter("vin", "some");
|
||||
|
||||
q.executeUpdate();
|
||||
|
||||
t.commit();
|
||||
t = s.beginTransaction();
|
||||
|
||||
s.createQuery( "delete Vehicle" ).executeUpdate();
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
data.cleanup();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertWithSubqueriesAndNamedParams() {
|
||||
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, (select a.description from Animal a where a.description = :description), :vin from Car" );
|
||||
q.setParameter("id", 5l);
|
||||
q.setParameter("description", "Frog");
|
||||
q.setParameter("vin", "some");
|
||||
|
||||
q.executeUpdate();
|
||||
|
||||
t.commit();
|
||||
t = s.beginTransaction();
|
||||
|
||||
try {
|
||||
org.hibernate.Query q1 = s.createQuery( "insert into Pickup (id, owner, vin) select :id, (select :description from Animal a where a.description = :description), :vin from Car" );
|
||||
fail("Unsupported exception should have been thrown");
|
||||
} catch(QueryException e) {
|
||||
assertTrue(e.getMessage().indexOf("Use of parameters in subqueries of INSERT INTO DML statements is not supported.") > -1);
|
||||
}
|
||||
|
||||
t = s.beginTransaction();
|
||||
|
||||
|
||||
s.createQuery( "delete Vehicle" ).executeUpdate();
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
data.cleanup();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleInsertTypeMismatchException() {
|
||||
|
||||
|
|
Loading…
Reference in New Issue