Skip to content

Commit d9646ba

Browse files
committed
[hibernate#2055] Add test for Setting hibernate.query.mutation_strategy.global_temporary.create_tables to false has no effect
1 parent ec8d12f commit d9646ba

File tree

3 files changed

+333
-0
lines changed

3 files changed

+333
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive.schema;
7+
8+
import java.util.List;
9+
import java.util.concurrent.CompletionStage;
10+
import java.util.function.Consumer;
11+
12+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
13+
import org.hibernate.cfg.Configuration;
14+
import org.hibernate.dialect.Dialect;
15+
import org.hibernate.dialect.temptable.TemporaryTable;
16+
import org.hibernate.reactive.BaseReactiveTest;
17+
import org.hibernate.reactive.provider.Settings;
18+
import org.hibernate.reactive.testing.SqlStatementTracker;
19+
import org.hibernate.reactive.util.impl.CompletionStages;
20+
21+
import org.junit.jupiter.api.AfterEach;
22+
23+
import io.vertx.junit5.VertxTestContext;
24+
import jakarta.persistence.Entity;
25+
import jakarta.persistence.GeneratedValue;
26+
import jakarta.persistence.Id;
27+
import jakarta.persistence.Inheritance;
28+
import jakarta.persistence.InheritanceType;
29+
30+
import static org.assertj.core.api.Assertions.assertThat;
31+
import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture;
32+
33+
public abstract class AbstractTemporaryTableTest extends BaseReactiveTest {
34+
private static SqlStatementTracker sqlStatementTracker;
35+
36+
final static Dialect[] dialect = new Dialect[1];
37+
38+
@FunctionalInterface
39+
protected interface CheckTemporaryTableCommandExecution {
40+
void check();
41+
}
42+
43+
@Override
44+
public void before(VertxTestContext context) {
45+
}
46+
47+
@AfterEach
48+
public void after(VertxTestContext context) {
49+
sqlStatementTracker.clear();
50+
super.after( context );
51+
}
52+
53+
@Override
54+
public CompletionStage<Void> deleteEntities(Class<?>... entities) {
55+
return voidFuture();
56+
}
57+
58+
@Override
59+
protected void addServices(StandardServiceRegistryBuilder builder) {
60+
if ( sqlStatementTracker != null ) {
61+
sqlStatementTracker.registerService( builder );
62+
}
63+
}
64+
65+
protected void testTemporaryTableCreation(
66+
Consumer<Configuration> configure,
67+
CheckTemporaryTableCommandExecution temporaryTableCreationCheck,
68+
CheckTemporaryTableCommandExecution temporaryTableDopCheck,
69+
VertxTestContext context) {
70+
test( context, setupSessionFactory( constructConfiguration( configure ) )
71+
.thenCompose( v -> getSessionFactory().withSession( s -> {
72+
dialect[0] = getDialect();
73+
temporaryTableCreationCheck.check();
74+
sqlStatementTracker.clear();
75+
return voidFuture();
76+
} ) )
77+
// to ensure the factory is always closed even in case of exceptions
78+
.handle( CompletionStages::handle )
79+
.thenCompose( handler -> factoryManager.stop()
80+
.handle( CompletionStages::handle )
81+
// returns the exception thrown before the factory was stopped (if there was one)
82+
.thenCompose( unused -> handler.getResultAsCompletionStage() )
83+
.thenAccept( v -> {
84+
temporaryTableDopCheck.check();
85+
} )
86+
)
87+
);
88+
}
89+
90+
private Configuration constructConfiguration(Consumer<Configuration> configure) {
91+
Configuration configuration = super.constructConfiguration();
92+
configuration.setProperty( Settings.HBM2DDL_AUTO, "create" );
93+
configuration.addAnnotatedClass( Engineer.class );
94+
configuration.addAnnotatedClass( Doctor.class );
95+
configuration.addAnnotatedClass( Person.class );
96+
97+
sqlStatementTracker = new SqlStatementTracker(
98+
AbstractTemporaryTableTest::filter,
99+
configuration.getProperties()
100+
);
101+
102+
configure.accept( configuration );
103+
return configuration;
104+
}
105+
106+
protected static void assertNumberOfTemporaryTableCreated(int expectedNumberOfCreatedTable, String errorMessage) {
107+
assertThat( getNumberOfCommandExecuted( dialect[0].getTemporaryTableCreateCommand() ) )
108+
.as( errorMessage )
109+
.isEqualTo( expectedNumberOfCreatedTable );
110+
}
111+
112+
protected static void assertNumberOfTemporaryTableDropped(int expectedNumberOfCreatedTable, String errorMessage) {
113+
assertThat( getNumberOfCommandExecuted( dialect[0].getTemporaryTableDropCommand() ) )
114+
.as( errorMessage )
115+
.isEqualTo( expectedNumberOfCreatedTable );
116+
}
117+
118+
private static long getNumberOfCommandExecuted(String temporaryTableCommand) {
119+
List<String> loggedQueries = sqlStatementTracker.getLoggedQueries();
120+
return loggedQueries.stream().filter( q -> q.contains( temporaryTableCommand ) && q.contains( TemporaryTable.ID_TABLE_PREFIX )).count();
121+
}
122+
123+
private static boolean filter(String s) {
124+
String[] accepted = { "create", "drop" };
125+
for ( String valid : accepted ) {
126+
if ( s.toLowerCase().startsWith( valid ) ) {
127+
return true;
128+
}
129+
}
130+
return false;
131+
}
132+
133+
@Entity(name = "Person")
134+
@Inheritance(strategy = InheritanceType.JOINED)
135+
public static class Person {
136+
137+
@Id
138+
@GeneratedValue
139+
private Long id;
140+
141+
private String name;
142+
143+
private boolean employed;
144+
145+
public Long getId() {
146+
return id;
147+
}
148+
149+
public void setId(Long id) {
150+
this.id = id;
151+
}
152+
153+
public String getName() {
154+
return name;
155+
}
156+
157+
public void setName(String name) {
158+
this.name = name;
159+
}
160+
161+
public boolean isEmployed() {
162+
return employed;
163+
}
164+
165+
public void setEmployed(boolean employed) {
166+
this.employed = employed;
167+
}
168+
}
169+
170+
@Entity(name = "Doctor")
171+
public static class Doctor extends Person {
172+
}
173+
174+
@Entity(name = "Engineer")
175+
public static class Engineer extends Person {
176+
177+
private boolean fellow;
178+
179+
public boolean isFellow() {
180+
return fellow;
181+
}
182+
183+
public void setFellow(boolean fellow) {
184+
this.fellow = fellow;
185+
}
186+
}
187+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive.schema;
7+
8+
9+
import java.util.function.Consumer;
10+
import java.util.stream.Stream;
11+
12+
import org.hibernate.cfg.Configuration;
13+
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableStrategy;
14+
import org.hibernate.reactive.annotations.EnabledFor;
15+
import org.hibernate.reactive.containers.DatabaseConfiguration;
16+
17+
import org.junit.jupiter.params.ParameterizedTest;
18+
import org.junit.jupiter.params.provider.Arguments;
19+
import org.junit.jupiter.params.provider.MethodSource;
20+
21+
import io.vertx.junit5.Timeout;
22+
import io.vertx.junit5.VertxTestContext;
23+
24+
import static java.util.concurrent.TimeUnit.MINUTES;
25+
import static org.junit.jupiter.params.provider.Arguments.arguments;
26+
27+
@Timeout(value = 10, timeUnit = MINUTES)
28+
@EnabledFor(value = DatabaseConfiguration.DBType.ORACLE, reason = "It uses GlobalTemporaryTableStrategy by default")
29+
public class GlobalTemporaryTableTest extends AbstractTemporaryTableTest {
30+
31+
public static Stream<Arguments> settings() {
32+
return Stream.of(
33+
arguments(
34+
(Consumer<Configuration>) (Configuration configuration) -> {
35+
configuration.setProperty( GlobalTemporaryTableStrategy.CREATE_ID_TABLES, "true" );
36+
configuration.setProperty( GlobalTemporaryTableStrategy.DROP_ID_TABLES, "true" );
37+
},
38+
(CheckTemporaryTableCommandExecution) () -> assertNumberOfTemporaryTableCreated(
39+
1,
40+
"Temporary table has not been created even if CREATE_ID_TABLES is true"
41+
),
42+
(CheckTemporaryTableCommandExecution) () -> assertNumberOfTemporaryTableDropped(
43+
1,
44+
"Temporary table has not been dropped even if DROP_ID_TABLES is true"
45+
)
46+
),
47+
arguments(
48+
(Consumer<Configuration>) (Configuration configuration) -> {
49+
configuration.setProperty( GlobalTemporaryTableStrategy.CREATE_ID_TABLES, "false" );
50+
configuration.setProperty( GlobalTemporaryTableStrategy.DROP_ID_TABLES, "false" );
51+
},
52+
(CheckTemporaryTableCommandExecution) () -> assertNumberOfTemporaryTableCreated(
53+
0,
54+
"Temporary table has been created even if CREATE_ID_TABLES is false"
55+
),
56+
(CheckTemporaryTableCommandExecution) () -> assertNumberOfTemporaryTableDropped(
57+
0,
58+
"Temporary table has been dropped even if DROP_ID_TABLES is false"
59+
)
60+
)
61+
);
62+
}
63+
64+
@ParameterizedTest
65+
@MethodSource("settings")
66+
public void testGlobalTemporaryTableCreation(
67+
Consumer<Configuration> configure,
68+
CheckTemporaryTableCommandExecution temporaryTableCreationCheck,
69+
CheckTemporaryTableCommandExecution temporaryTableDopCheck,
70+
VertxTestContext context) {
71+
testTemporaryTableCreation( configure, temporaryTableCreationCheck, temporaryTableDopCheck, context );
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive.schema;
7+
8+
import java.util.function.Consumer;
9+
import java.util.stream.Stream;
10+
11+
import org.hibernate.cfg.Configuration;
12+
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableStrategy;
13+
import org.hibernate.reactive.annotations.EnabledFor;
14+
import org.hibernate.reactive.containers.DatabaseConfiguration;
15+
16+
import org.junit.jupiter.params.ParameterizedTest;
17+
import org.junit.jupiter.params.provider.Arguments;
18+
import org.junit.jupiter.params.provider.MethodSource;
19+
20+
import io.vertx.junit5.Timeout;
21+
import io.vertx.junit5.VertxTestContext;
22+
23+
import static java.util.concurrent.TimeUnit.MINUTES;
24+
import static org.junit.jupiter.params.provider.Arguments.arguments;
25+
26+
@Timeout(value = 10, timeUnit = MINUTES)
27+
@EnabledFor(value = DatabaseConfiguration.DBType.COCKROACHDB, reason = "It uses PersistentTemporaryTableStrategy by default")
28+
@EnabledFor(value = DatabaseConfiguration.DBType.SQLSERVER, reason = "It uses PersistentTemporaryTableStrategy by default")
29+
public class PersistentTemporaryTableTest extends AbstractTemporaryTableTest {
30+
31+
public static Stream<Arguments> settings() {
32+
return Stream.of(
33+
arguments(
34+
(Consumer<Configuration>) (Configuration configuration) -> {
35+
configuration.setProperty( PersistentTableStrategy.CREATE_ID_TABLES, "true" );
36+
configuration.setProperty( PersistentTableStrategy.DROP_ID_TABLES, "true" );
37+
},
38+
(CheckTemporaryTableCommandExecution) () -> assertNumberOfTemporaryTableCreated(
39+
1,
40+
"Temporary table has not been created even if CREATE_ID_TABLES is true"
41+
),
42+
(CheckTemporaryTableCommandExecution) () -> assertNumberOfTemporaryTableDropped(
43+
1,
44+
"Temporary table has not been dropped even if DROP_ID_TABLES is true"
45+
)
46+
),
47+
arguments(
48+
(Consumer<Configuration>) (Configuration configuration) -> {
49+
configuration.setProperty( PersistentTableStrategy.CREATE_ID_TABLES, "false" );
50+
configuration.setProperty( PersistentTableStrategy.DROP_ID_TABLES, "false" );
51+
},
52+
(CheckTemporaryTableCommandExecution) () -> assertNumberOfTemporaryTableCreated(
53+
0,
54+
"Temporary table has been created even if CREATE_ID_TABLES is false"
55+
),
56+
(CheckTemporaryTableCommandExecution) () -> assertNumberOfTemporaryTableDropped(
57+
0,
58+
"Temporary table has been dropped even if DROP_ID_TABLES is false"
59+
)
60+
)
61+
);
62+
}
63+
64+
@ParameterizedTest
65+
@MethodSource("settings")
66+
public void testPersistentTemporaryTableCreation(
67+
Consumer<Configuration> configure,
68+
CheckTemporaryTableCommandExecution temporaryTableCreationCheck,
69+
CheckTemporaryTableCommandExecution temporaryTableDopCheck,
70+
VertxTestContext context) {
71+
testTemporaryTableCreation( configure, temporaryTableCreationCheck, temporaryTableDopCheck, context );
72+
}
73+
}

0 commit comments

Comments
 (0)