mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-17 00:24:57 +00:00
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.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import antlr.SemanticException;
|
|
||||||
import antlr.collections.AST;
|
|
||||||
|
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
|
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
|
||||||
import org.hibernate.hql.internal.antlr.SqlTokenTypes;
|
import org.hibernate.hql.internal.antlr.SqlTokenTypes;
|
||||||
import org.hibernate.hql.internal.ast.util.ASTAppender;
|
import org.hibernate.hql.internal.ast.util.ASTAppender;
|
||||||
import org.hibernate.hql.internal.ast.util.ASTIterator;
|
import org.hibernate.hql.internal.ast.util.ASTIterator;
|
||||||
import org.hibernate.hql.internal.ast.util.ASTPrinter;
|
import org.hibernate.hql.internal.ast.util.ASTPrinter;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
import antlr.SemanticException;
|
||||||
|
import antlr.collections.AST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the list of expressions in a SELECT clause.
|
* Represents the list of expressions in a SELECT clause.
|
||||||
*
|
*
|
||||||
@ -139,6 +140,11 @@ public void initializeExplicitSelectClause(FromClause fromClause) throws Semanti
|
|||||||
// changes the AST!!!
|
// changes the AST!!!
|
||||||
SelectExpression[] selectExpressions = collectSelectExpressions();
|
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++ ) {
|
for ( int i = 0; i < selectExpressions.length; i++ ) {
|
||||||
SelectExpression selectExpression = selectExpressions[i];
|
SelectExpression selectExpression = selectExpressions[i];
|
||||||
|
|
||||||
@ -148,6 +154,17 @@ public void initializeExplicitSelectClause(FromClause fromClause) throws Semanti
|
|||||||
scalarSelect = true;
|
scalarSelect = true;
|
||||||
}
|
}
|
||||||
else {
|
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();
|
Type type = selectExpression.getDataType();
|
||||||
if ( type == null ) {
|
if ( type == null ) {
|
||||||
throw new IllegalStateException( "No data type for node: " + selectExpression.getClass().getName() + " "
|
throw new IllegalStateException( "No data type for node: " + selectExpression.getClass().getName() + " "
|
||||||
|
@ -209,6 +209,19 @@ public void testSimpleInsert() {
|
|||||||
data.cleanup();
|
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
|
@Test
|
||||||
public void testSimpleInsertWithNamedParam() {
|
public void testSimpleInsertWithNamedParam() {
|
||||||
TestData data = new TestData();
|
TestData data = new TestData();
|
||||||
@ -233,6 +246,67 @@ public void testSimpleInsertWithNamedParam() {
|
|||||||
data.cleanup();
|
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
|
@Test
|
||||||
public void testSimpleInsertTypeMismatchException() {
|
public void testSimpleInsertTypeMismatchException() {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user