mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-19 17:45:10 +00:00
HHH-15528 Add Cockroach to Jenkins nightly test matrix and fix issues
This commit is contained in:
parent
495849437f
commit
14d1c65802
2
.github/workflows/contributor-build.yml
vendored
2
.github/workflows/contributor-build.yml
vendored
@ -47,6 +47,8 @@ jobs:
|
||||
- rdbms: db2
|
||||
- rdbms: mssql
|
||||
- rdbms: sybase
|
||||
# Running with CockroachDB requires at least 2-4 vCPUs, which we don't have on GH Actions runners
|
||||
# - rdbms: cockroachdb
|
||||
# Running with HANA requires at least 8GB memory just for the database, which we don't have on GH Actions runners
|
||||
# - rdbms: hana
|
||||
steps:
|
||||
|
106
Jenkinsfile
vendored
106
Jenkinsfile
vendored
@ -24,7 +24,6 @@ import org.hibernate.jenkins.pipeline.helpers.job.JobHelper
|
||||
this.helper = new JobHelper(this)
|
||||
|
||||
helper.runWithNotification {
|
||||
def defaultJdk = '11'
|
||||
stage('Configure') {
|
||||
this.environments = [
|
||||
// new BuildEnvironment( dbName: 'h2' ),
|
||||
@ -39,9 +38,11 @@ stage('Configure') {
|
||||
// new BuildEnvironment( dbName: 'db2' ),
|
||||
// new BuildEnvironment( dbName: 'mssql' ),
|
||||
// new BuildEnvironment( dbName: 'sybase' ),
|
||||
new BuildEnvironment( dbName: 'hana', node: 'HANA' ),
|
||||
new BuildEnvironment( dbName: 's390x', node: 's390x' ),
|
||||
new BuildEnvironment( dbName: 'tidb', node: 'tidb', notificationRecipients: 'tidb_hibernate@pingcap.com' ),
|
||||
new BuildEnvironment( dbName: 'hana_jenkins', node: 'HANA', dbLockableResource: 'HANA' ),
|
||||
new BuildEnvironment( node: 's390x' ),
|
||||
new BuildEnvironment( dbName: 'tidb', node: 'tidb', dbLockableResource: 'TIDB',
|
||||
additionalOptions: '-DdbHost=localhost:4000',
|
||||
notificationRecipients: 'tidb_hibernate@pingcap.com' ),
|
||||
// Disable EDB for now as the image is not available anymore
|
||||
// new BuildEnvironment( dbName: 'edb' ),
|
||||
new BuildEnvironment( testJdkVersion: '17' ),
|
||||
@ -53,11 +54,17 @@ stage('Configure') {
|
||||
new BuildEnvironment( testJdkVersion: '20', testJdkLauncherArgs: '--enable-preview' )
|
||||
];
|
||||
|
||||
if ( env.CHANGE_ID ) {
|
||||
if ( pullRequest.labels.contains( 'cockroachdb' ) ) {
|
||||
this.environments.add( new BuildEnvironment( dbName: 'cockroachdb', node: 'LongDuration', longRunning: true ) )
|
||||
}
|
||||
}
|
||||
|
||||
helper.configure {
|
||||
file 'job-configuration.yaml'
|
||||
// We don't require the following, but the build helper plugin apparently does
|
||||
jdk {
|
||||
defaultTool "OpenJDK ${defaultJdk} Latest"
|
||||
defaultTool DEFAULT_JDK_TOOL
|
||||
}
|
||||
maven {
|
||||
defaultTool 'Apache Maven 3.8'
|
||||
@ -96,7 +103,7 @@ stage('Build') {
|
||||
if ( buildEnv.testJdkVersion ) {
|
||||
testJavaHome = tool(name: "OpenJDK ${buildEnv.testJdkVersion} Latest", type: 'jdk')
|
||||
}
|
||||
def javaHome = tool(name: "OpenJDK ${DEFAULT_JDK_VERSION} Latest", type: 'jdk')
|
||||
def javaHome = tool(name: DEFAULT_JDK_TOOL, type: 'jdk')
|
||||
// Use withEnv instead of setting env directly, as that is global!
|
||||
// See https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md
|
||||
withEnv(["JAVA_HOME=${javaHome}", "PATH+JAVA=${javaHome}/bin"]) {
|
||||
@ -116,6 +123,13 @@ stage('Build') {
|
||||
try {
|
||||
stage('Start database') {
|
||||
switch (buildEnv.dbName) {
|
||||
case "cockroachdb":
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('cockroachdb/cockroach:v21.1.21').pull()
|
||||
}
|
||||
sh "./docker_db.sh cockroachdb"
|
||||
state[buildEnv.tag]['containerName'] = "cockroach"
|
||||
break;
|
||||
case "mysql":
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('mysql:5.7').pull()
|
||||
@ -155,7 +169,7 @@ stage('Build') {
|
||||
break;
|
||||
case "oracle":
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('quillbuilduser/oracle-18-xe').pull()
|
||||
docker.image('gvenzl/oracle-xe:18.4.0-full').pull()
|
||||
}
|
||||
sh "./docker_db.sh oracle_18"
|
||||
state[buildEnv.tag]['containerName'] = "oracle"
|
||||
@ -192,38 +206,25 @@ stage('Build') {
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
switch (buildEnv.dbName) {
|
||||
case "h2":
|
||||
case "derby":
|
||||
case "hsqldb":
|
||||
runTest("-Pdb=${buildEnv.dbName}${state[buildEnv.tag]['additionalOptions']}")
|
||||
break;
|
||||
case "mysql":
|
||||
case "mysql8":
|
||||
runTest("-Pdb=mysql_ci${state[buildEnv.tag]['additionalOptions']}")
|
||||
break;
|
||||
case "tidb":
|
||||
runTest("-Pdb=tidb -DdbHost=localhost:4000${state[buildEnv.tag]['additionalOptions']}", 'TIDB')
|
||||
break;
|
||||
case "postgresql":
|
||||
case "postgresql_13":
|
||||
runTest("-Pdb=pgsql_ci${state[buildEnv.tag]['additionalOptions']}")
|
||||
break;
|
||||
case "oracle":
|
||||
runTest("-Pdb=oracle_ci -PexcludeTests=**.LockTest.testQueryTimeout*${state[buildEnv.tag]['additionalOptions']}")
|
||||
break;
|
||||
case "hana":
|
||||
runTest("-Pdb=hana_jenkins${state[buildEnv.tag]['additionalOptions']}", 'HANA')
|
||||
break;
|
||||
case "edb":
|
||||
runTest("-Pdb=edb_ci -DdbHost=localhost:5433${state[buildEnv.tag]['additionalOptions']}")
|
||||
break;
|
||||
case "s390x":
|
||||
runTest("-Pdb=h2${state[buildEnv.tag]['additionalOptions']}")
|
||||
break;
|
||||
default:
|
||||
runTest("-Pdb=${buildEnv.dbName}_ci${state[buildEnv.tag]['additionalOptions']}")
|
||||
break;
|
||||
String cmd = "./ci/build.sh ${buildEnv.additionalOptions ?: ''} ${state[buildEnv.tag]['additionalOptions'] ?: ''}"
|
||||
withEnv(["RDBMS=${buildEnv.dbName}"]) {
|
||||
try {
|
||||
if (buildEnv.dbLockableResource == null) {
|
||||
timeout( [time: buildEnv.longRunning ? 240 : 120, unit: 'MINUTES'] ) {
|
||||
sh cmd
|
||||
}
|
||||
}
|
||||
else {
|
||||
lock(buildEnv.dbLockableResource) {
|
||||
timeout( [time: buildEnv.longRunning ? 240 : 120, unit: 'MINUTES'] ) {
|
||||
sh cmd
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
junit '**/target/test-results/test/*.xml,**/target/test-results/testKitTest/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -252,10 +253,13 @@ class BuildEnvironment {
|
||||
String testJdkLauncherArgs
|
||||
String dbName = 'h2'
|
||||
String node
|
||||
String dbLockableResource
|
||||
String additionalOptions
|
||||
String notificationRecipients
|
||||
boolean longRunning
|
||||
|
||||
String toString() { getTag() }
|
||||
String getTag() { "${testJdkVersion ? 'jdk_' + testJdkVersion + '_' : '' }${dbName}" }
|
||||
String getTag() { "${node ? node + "_" : ''}${testJdkVersion ? 'jdk_' + testJdkVersion + '_' : '' }${dbName}" }
|
||||
}
|
||||
|
||||
void runBuildOnNode(String label, Closure body) {
|
||||
@ -281,28 +285,6 @@ void pruneDockerContainers() {
|
||||
sh 'docker volume prune -f || true'
|
||||
}
|
||||
}
|
||||
// Clean by default otherwise the PackagedEntityManager tests fail on a node that previously ran a different DB
|
||||
void runTest(String goal, String lockableResource = null, boolean clean = true) {
|
||||
String cmd = "./gradlew" + (clean ? " clean" : "") + " check ${goal} -Plog-test-progress=true --stacktrace";
|
||||
try {
|
||||
if (lockableResource == null) {
|
||||
timeout( [time: 120, unit: 'MINUTES'] ) {
|
||||
sh cmd
|
||||
}
|
||||
}
|
||||
else {
|
||||
lock(lockableResource) {
|
||||
timeout( [time: 120, unit: 'MINUTES'] ) {
|
||||
sh cmd
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
junit '**/target/test-results/test/*.xml,**/target/test-results/testKitTest/*.xml'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleNotifications(currentBuild, buildEnv) {
|
||||
def currentResult = getParallelResult(currentBuild, buildEnv.tag)
|
||||
|
29
ci/build.sh
29
ci/build.sh
@ -1,8 +1,13 @@
|
||||
#! /bin/bash
|
||||
|
||||
goal=
|
||||
if [ "$RDBMS" == "derby" ]; then
|
||||
if [ "$RDBMS" == "h2" ]; then
|
||||
# This is the default.
|
||||
goal=""
|
||||
elif [ "$RDBMS" == "derby" ]; then
|
||||
goal="-Pdb=derby"
|
||||
elif [ "$RDBMS" == "edb" ]; then
|
||||
goal="-Pdb=edb_ci"
|
||||
elif [ "$RDBMS" == "hsqldb" ]; then
|
||||
goal="-Pdb=hsqldb"
|
||||
elif [ "$RDBMS" == "mysql8" ]; then
|
||||
@ -17,6 +22,7 @@ elif [ "$RDBMS" == "postgresql_13" ]; then
|
||||
goal="-Pdb=pgsql_ci"
|
||||
elif [ "$RDBMS" == "oracle" ]; then
|
||||
# I have no idea why, but these tests don't work on GH Actions
|
||||
# yrodiere: Apparently those have been disabled on Jenkins as well...
|
||||
goal="-Pdb=oracle_ci -PexcludeTests=**.LockTest.testQueryTimeout*"
|
||||
elif [ "$RDBMS" == "db2" ]; then
|
||||
goal="-Pdb=db2_ci"
|
||||
@ -24,8 +30,27 @@ elif [ "$RDBMS" == "mssql" ]; then
|
||||
goal="-Pdb=mssql_ci"
|
||||
elif [ "$RDBMS" == "hana" ]; then
|
||||
goal="-Pdb=hana_ci"
|
||||
elif [ "$RDBMS" == "hana_jenkins" ]; then
|
||||
goal="-Pdb=hana_jenkins"
|
||||
elif [ "$RDBMS" == "sybase" ]; then
|
||||
goal="-Pdb=sybase_ci"
|
||||
elif [ "$RDBMS" == "tidb" ]; then
|
||||
goal="-Pdb=tidb"
|
||||
elif [ "$RDBMS" == "cockroachdb" ]; then
|
||||
goal="-Pdb=cockroachdb"
|
||||
fi
|
||||
|
||||
exec ./gradlew check ${goal} -Plog-test-progress=true --stacktrace
|
||||
# Only run checkstyle in the H2 build,
|
||||
# so that CI jobs give a more complete report
|
||||
# and developers can fix code style and non-H2 DB tests in parallel.
|
||||
if [ -n "$goal" ]; then
|
||||
goal="$goal -x checkstyleMain"
|
||||
fi
|
||||
|
||||
function logAndExec() {
|
||||
echo 1>&2 "Executing:" "${@}"
|
||||
exec "${@}"
|
||||
}
|
||||
|
||||
# Clean by default otherwise the PackagedEntityManager tests fail on a node that previously ran a different DB
|
||||
logAndExec ./gradlew clean check ${goal} "${@}" -Plog-test-progress=true --stacktrace
|
||||
|
@ -22,4 +22,6 @@ elif [ "$RDBMS" == 'hana' ]; then
|
||||
bash $DIR/../docker_db.sh hana
|
||||
elif [ "$RDBMS" == 'sybase' ]; then
|
||||
bash $DIR/../docker_db.sh sybase
|
||||
elif [ "$RDBMS" == 'cockroachdb' ]; then
|
||||
bash $DIR/../docker_db.sh cockroachdb
|
||||
fi
|
24
docker_db.sh
24
docker_db.sh
@ -485,8 +485,16 @@ hana() {
|
||||
|
||||
cockroachdb() {
|
||||
$CONTAINER_CLI rm -f cockroach || true
|
||||
$CONTAINER_CLI run -d --name=cockroach -p 26257:26257 -p 8080:8080 docker.io/cockroachdb/cockroach:v21.2.10 start-single-node \
|
||||
--insecure --store=type=mem,size=0.25 --advertise-addr=localhost
|
||||
LOG_CONFIG="
|
||||
sinks:
|
||||
stderr:
|
||||
channels: all
|
||||
filter: ERROR
|
||||
redact: false
|
||||
exit-on-error: true
|
||||
"
|
||||
$CONTAINER_CLI run -d --name=cockroach -m 3g -p 26257:26257 -p 8080:8080 docker.io/cockroachdb/cockroach:v21.2.16 start-single-node \
|
||||
--insecure --store=type=mem,size=640MiB --advertise-addr=localhost --log="$LOG_CONFIG"
|
||||
OUTPUT=
|
||||
while [[ $OUTPUT != *"CockroachDB node starting"* ]]; do
|
||||
echo "Waiting for CockroachDB to start..."
|
||||
@ -494,9 +502,9 @@ cockroachdb() {
|
||||
# Note we need to redirect stderr to stdout to capture the logs
|
||||
OUTPUT=$($CONTAINER_CLI logs cockroach 2>&1)
|
||||
done
|
||||
echo "Enabling experimental box2d operators and some ptimized settings for running the tests"
|
||||
echo "Enabling experimental box2d operators and some optimized settings for running the tests"
|
||||
#settings documented in https://www.cockroachlabs.com/docs/v21.2/local-testing.html#use-a-local-single-node-cluster-with-in-memory-storage
|
||||
$CONTAINER_CLI exec -it cockroach bash -c "cat <<EOF | ./cockroach sql --insecure
|
||||
$CONTAINER_CLI exec cockroach bash -c "cat <<EOF | ./cockroach sql --insecure
|
||||
SET CLUSTER SETTING sql.spatial.experimental_box2d_comparison_operators.enabled = on;
|
||||
SET CLUSTER SETTING kv.raft_log.disable_synchronization_unsafe = true;
|
||||
SET CLUSTER SETTING kv.range_merge.queue_interval = '50ms';
|
||||
@ -506,8 +514,12 @@ SET CLUSTER SETTING jobs.retention_time = '15s';
|
||||
SET CLUSTER SETTING schemachanger.backfiller.buffer_increment = '128 KiB';
|
||||
SET CLUSTER SETTING sql.stats.automatic_collection.enabled = false;
|
||||
SET CLUSTER SETTING kv.range_split.by_load_merge_delay = '5s';
|
||||
ALTER RANGE default CONFIGURE ZONE USING "gc.ttlseconds" = 5;
|
||||
ALTER DATABASE system CONFIGURE ZONE USING "gc.ttlseconds" = 5;
|
||||
SET CLUSTER SETTING timeseries.storage.enabled = false;
|
||||
SET CLUSTER SETTING timeseries.storage.resolution_10s.ttl = '0s';
|
||||
SET CLUSTER SETTING timeseries.storage.resolution_30m.ttl = '0s';
|
||||
ALTER RANGE default CONFIGURE ZONE USING \"gc.ttlseconds\" = 10;
|
||||
ALTER DATABASE system CONFIGURE ZONE USING \"gc.ttlseconds\" = 10;
|
||||
ALTER DATABASE defaultdb CONFIGURE ZONE USING \"gc.ttlseconds\" = 10;
|
||||
quit
|
||||
EOF
|
||||
"
|
||||
|
@ -17,6 +17,7 @@
|
||||
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
|
||||
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
@ -39,34 +40,35 @@ public void verifyMappings(SessionFactoryScope scope) {
|
||||
final MappingMetamodelImplementor mappingMetamodel = scope.getSessionFactory()
|
||||
.getRuntimeMetamodels()
|
||||
.getMappingMetamodel();
|
||||
final JdbcTypeRegistry jdbcTypeRegistry = mappingMetamodel.getTypeConfiguration().getJdbcTypeRegistry();
|
||||
final EntityPersister entityDescriptor = mappingMetamodel.getEntityDescriptor(EntityOfByteArrays.class);
|
||||
|
||||
{
|
||||
final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("primitive");
|
||||
final JdbcMapping jdbcMapping = primitive.getJdbcMapping();
|
||||
assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(byte[].class));
|
||||
assertThat( jdbcMapping.getJdbcType().getJdbcTypeCode(), equalTo( Types.VARBINARY));
|
||||
assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.VARBINARY ) ) );
|
||||
}
|
||||
|
||||
{
|
||||
final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("wrapper");
|
||||
final JdbcMapping jdbcMapping = primitive.getJdbcMapping();
|
||||
assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(Byte[].class));
|
||||
assertThat( jdbcMapping.getJdbcType().getJdbcTypeCode(), equalTo( Types.VARBINARY));
|
||||
assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.VARBINARY ) ) );
|
||||
}
|
||||
|
||||
{
|
||||
final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("primitiveLob");
|
||||
final JdbcMapping jdbcMapping = primitive.getJdbcMapping();
|
||||
assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(byte[].class));
|
||||
assertThat( jdbcMapping.getJdbcType().getJdbcTypeCode(), equalTo( Types.BLOB));
|
||||
assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.BLOB ) ) );
|
||||
}
|
||||
|
||||
{
|
||||
final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("wrapperLob");
|
||||
final JdbcMapping jdbcMapping = primitive.getJdbcMapping();
|
||||
assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(Byte[].class));
|
||||
assertThat( jdbcMapping.getJdbcType().getJdbcTypeCode(), equalTo( Types.BLOB));
|
||||
assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.BLOB ) ) );
|
||||
}
|
||||
|
||||
scope.inTransaction(
|
||||
|
@ -144,36 +144,43 @@ protected SessionFactory sessionFactory(Map<String, Object> settings) {
|
||||
HibernateSchemaManagementTool tool = new HibernateSchemaManagementTool();
|
||||
tool.injectServices(serviceRegistry);
|
||||
|
||||
final GenerationTargetToDatabase frontEndSchemaGenerator = new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get(FRONT_END_TENANT)
|
||||
)
|
||||
);
|
||||
final GenerationTargetToDatabase backEndSchemaGenerator = new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get(BACK_END_TENANT)
|
||||
)
|
||||
);
|
||||
|
||||
new SchemaDropperImpl(serviceRegistry).doDrop(
|
||||
new SchemaDropperImpl( serviceRegistry ).doDrop(
|
||||
metadata,
|
||||
serviceRegistry,
|
||||
settings,
|
||||
true,
|
||||
frontEndSchemaGenerator,
|
||||
backEndSchemaGenerator
|
||||
);
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get( FRONT_END_TENANT )
|
||||
)
|
||||
),
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get( BACK_END_TENANT )
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
new SchemaCreatorImpl(serviceRegistry).doCreation(
|
||||
new SchemaCreatorImpl( serviceRegistry ).doCreation(
|
||||
metadata,
|
||||
serviceRegistry,
|
||||
settings,
|
||||
true,
|
||||
frontEndSchemaGenerator,
|
||||
backEndSchemaGenerator
|
||||
);
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get( FRONT_END_TENANT )
|
||||
)
|
||||
),
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get( BACK_END_TENANT )
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
final SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder();
|
||||
return sessionFactoryBuilder.build();
|
||||
|
@ -232,36 +232,43 @@ protected SessionFactory sessionFactory(Map<String, Object> settings) {
|
||||
HibernateSchemaManagementTool tool = new HibernateSchemaManagementTool();
|
||||
tool.injectServices(serviceRegistry);
|
||||
|
||||
final GenerationTargetToDatabase frontEndSchemaGenerator = new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get(FRONT_END_TENANT)
|
||||
)
|
||||
);
|
||||
final GenerationTargetToDatabase backEndSchemaGenerator = new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get(BACK_END_TENANT)
|
||||
)
|
||||
);
|
||||
|
||||
new SchemaDropperImpl(serviceRegistry).doDrop(
|
||||
new SchemaDropperImpl( serviceRegistry ).doDrop(
|
||||
metadata,
|
||||
serviceRegistry,
|
||||
settings,
|
||||
true,
|
||||
frontEndSchemaGenerator,
|
||||
backEndSchemaGenerator
|
||||
);
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get( FRONT_END_TENANT )
|
||||
)
|
||||
),
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get( BACK_END_TENANT )
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
new SchemaCreatorImpl(serviceRegistry).doCreation(
|
||||
new SchemaCreatorImpl( serviceRegistry ).doCreation(
|
||||
metadata,
|
||||
serviceRegistry,
|
||||
settings,
|
||||
true,
|
||||
frontEndSchemaGenerator,
|
||||
backEndSchemaGenerator
|
||||
);
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get( FRONT_END_TENANT )
|
||||
)
|
||||
),
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProviderMap.get( BACK_END_TENANT )
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
final SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder();
|
||||
return sessionFactoryBuilder.build();
|
||||
|
@ -132,15 +132,25 @@ xjc {
|
||||
}
|
||||
}
|
||||
|
||||
task copyBundleResources (type: Copy) {
|
||||
task copyBundleResourcesXml (type: Copy) {
|
||||
inputs.property( "db", db )
|
||||
ext {
|
||||
bundlesTargetDir = file( "${buildDir}/bundles" )
|
||||
bundleTokens = dbBundle[db]
|
||||
// Escape
|
||||
bundleTokens = [
|
||||
'db.dialect' : dbBundle[db]['db.dialect'].replace("&", "&"),
|
||||
'jdbc.driver' : dbBundle[db]['jdbc.driver'].replace("&", "&"),
|
||||
'jdbc.user' : dbBundle[db]['jdbc.user'].replace("&", "&"),
|
||||
'jdbc.pass' : dbBundle[db]['jdbc.pass'].replace("&", "&"),
|
||||
'jdbc.url' : dbBundle[db]['jdbc.url'].replace("&", "&"),
|
||||
'connection.init_sql' : dbBundle[db]['connection.init_sql'].replace("&", "&")
|
||||
]
|
||||
ext.bundleTokens['buildDirName'] = project.relativePath( buildDir )
|
||||
}
|
||||
|
||||
from file('src/test/bundles/templates')
|
||||
from('src/test/bundles/templates') {
|
||||
include '**/*.xml'
|
||||
}
|
||||
into ext.bundlesTargetDir
|
||||
filter( ReplaceTokens, tokens: ext.bundleTokens)
|
||||
|
||||
@ -149,6 +159,32 @@ task copyBundleResources (type: Copy) {
|
||||
}
|
||||
}
|
||||
|
||||
task copyBundleResourcesNonXml (type: Copy) {
|
||||
inputs.property( "db", db )
|
||||
ext {
|
||||
bundlesTargetDir = file( "${buildDir}/bundles" )
|
||||
// Escape
|
||||
bundleTokens = dbBundle[db]
|
||||
ext.bundleTokens['buildDirName'] = project.relativePath( buildDir )
|
||||
}
|
||||
|
||||
from('src/test/bundles/templates') {
|
||||
exclude '**/*.xml'
|
||||
}
|
||||
into ext.bundlesTargetDir
|
||||
filter( ReplaceTokens, tokens: ext.bundleTokens)
|
||||
|
||||
doFirst {
|
||||
ext.bundlesTargetDir.mkdirs()
|
||||
}
|
||||
}
|
||||
|
||||
task copyBundleResources (type: Copy) {
|
||||
inputs.property( "db", db )
|
||||
dependsOn tasks.copyBundleResourcesXml
|
||||
dependsOn tasks.copyBundleResourcesNonXml
|
||||
}
|
||||
|
||||
processTestResources {
|
||||
dependsOn copyBundleResources
|
||||
duplicatesStrategy = DuplicatesStrategy.WARN
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
import org.hibernate.QueryTimeoutException;
|
||||
import org.hibernate.boot.model.TypeContributions;
|
||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||
import org.hibernate.dialect.function.FormatFunction;
|
||||
@ -39,17 +41,16 @@
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
|
||||
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.IntervalType;
|
||||
import org.hibernate.query.sqm.NullOrdering;
|
||||
import org.hibernate.query.sqm.TemporalUnit;
|
||||
import org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.cte.CteMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
@ -58,6 +59,7 @@
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.InstantAsTimestampWithTimeZoneJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectNullAsBinaryTypeJdbcType;
|
||||
@ -68,11 +70,14 @@
|
||||
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.internal.Scale6IntervalSecondDdlType;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
||||
import static org.hibernate.query.sqm.TemporalUnit.DAY;
|
||||
import static org.hibernate.query.sqm.TemporalUnit.NATIVE;
|
||||
import static org.hibernate.type.SqlTypes.ARRAY;
|
||||
import static org.hibernate.type.SqlTypes.BINARY;
|
||||
import static org.hibernate.type.SqlTypes.BLOB;
|
||||
import static org.hibernate.type.SqlTypes.CHAR;
|
||||
@ -80,6 +85,7 @@
|
||||
import static org.hibernate.type.SqlTypes.GEOGRAPHY;
|
||||
import static org.hibernate.type.SqlTypes.GEOMETRY;
|
||||
import static org.hibernate.type.SqlTypes.INET;
|
||||
import static org.hibernate.type.SqlTypes.INTEGER;
|
||||
import static org.hibernate.type.SqlTypes.JSON;
|
||||
import static org.hibernate.type.SqlTypes.LONG32NVARCHAR;
|
||||
import static org.hibernate.type.SqlTypes.LONG32VARBINARY;
|
||||
@ -183,12 +189,13 @@ protected String columnType(int sqlTypeCode) {
|
||||
switch ( sqlTypeCode ) {
|
||||
case TINYINT:
|
||||
return "smallint"; //no tinyint
|
||||
case INTEGER:
|
||||
return "int4";
|
||||
|
||||
case CHAR:
|
||||
case NCHAR:
|
||||
case VARCHAR:
|
||||
return columnType( CHAR );
|
||||
case NVARCHAR:
|
||||
return "string($l)";
|
||||
return columnType( VARCHAR );
|
||||
|
||||
case NCLOB:
|
||||
case CLOB:
|
||||
@ -280,10 +287,46 @@ public JdbcType resolveSqlTypeDescriptor(
|
||||
jdbcTypeCode = TIMESTAMP_UTC;
|
||||
}
|
||||
break;
|
||||
case ARRAY:
|
||||
final JdbcType jdbcType = jdbcTypeRegistry.getDescriptor( jdbcTypeCode );
|
||||
// PostgreSQL names array types by prepending an underscore to the base name
|
||||
if ( jdbcType instanceof ArrayJdbcType && columnTypeName.charAt( 0 ) == '_' ) {
|
||||
final String componentTypeName = columnTypeName.substring( 1 );
|
||||
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
|
||||
if ( sqlTypeCode != null ) {
|
||||
return ( (ArrayJdbcType) jdbcType ).resolveType(
|
||||
jdbcTypeRegistry.getTypeConfiguration(),
|
||||
this,
|
||||
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
return jdbcType;
|
||||
}
|
||||
return jdbcTypeRegistry.getDescriptor( jdbcTypeCode );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer resolveSqlTypeCode(String columnTypeName, TypeConfiguration typeConfiguration) {
|
||||
switch ( columnTypeName ) {
|
||||
case "bool":
|
||||
return Types.BOOLEAN;
|
||||
case "float4":
|
||||
// Use REAL instead of FLOAT to get Float as recommended Java type
|
||||
return Types.REAL;
|
||||
case "float8":
|
||||
return Types.DOUBLE;
|
||||
case "int2":
|
||||
return Types.SMALLINT;
|
||||
case "int4":
|
||||
return Types.INTEGER;
|
||||
case "int8":
|
||||
return Types.BIGINT;
|
||||
}
|
||||
return super.resolveSqlTypeCode( columnTypeName, typeConfiguration );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||
super.contributeTypes( typeContributions, serviceRegistry );
|
||||
@ -309,6 +352,7 @@ public void contributeTypes(TypeContributions typeContributions, ServiceRegistry
|
||||
// Force Blob binding to byte[] for CockroachDB
|
||||
jdbcTypeRegistry.addDescriptor( Types.BLOB, VarbinaryJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptor( Types.CLOB, VarcharJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptor( Types.NCLOB, VarcharJdbcType.INSTANCE );
|
||||
|
||||
// The next two contributions are the same as for Postgresql
|
||||
typeContributions.contributeJdbcType( ObjectNullAsBinaryTypeJdbcType.INSTANCE );
|
||||
@ -335,6 +379,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
functionFactory.position();
|
||||
functionFactory.substringFromFor();
|
||||
functionFactory.locate_positionSubstring();
|
||||
functionFactory.concat_pipeOperator();
|
||||
functionFactory.trim2();
|
||||
functionFactory.substr();
|
||||
functionFactory.reverse();
|
||||
@ -349,6 +394,20 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
functionFactory.radians();
|
||||
functionFactory.pi();
|
||||
functionFactory.trunc(); //TODO: emulate second arg
|
||||
functionFactory.log();
|
||||
functionFactory.log10_log();
|
||||
|
||||
functionFactory.bitandorxornot_operator();
|
||||
functionFactory.bitAndOr();
|
||||
functionFactory.everyAny_boolAndOr();
|
||||
functionFactory.median_percentileCont_castDouble();
|
||||
functionFactory.stddev();
|
||||
functionFactory.stddevPopSamp();
|
||||
functionFactory.variance();
|
||||
functionFactory.varPopSamp();
|
||||
functionFactory.covarPopSamp();
|
||||
functionFactory.corr();
|
||||
functionFactory.regrLinearRegressionAggregates();
|
||||
|
||||
queryEngine.getSqmFunctionRegistry().register(
|
||||
"format",
|
||||
@ -357,7 +416,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
functionFactory.windowFunctions();
|
||||
functionFactory.listagg_stringAgg( "string" );
|
||||
functionFactory.inverseDistributionOrderedSetAggregates();
|
||||
functionFactory.hypotheticalOrderedSetAggregates();
|
||||
functionFactory.hypotheticalOrderedSetAggregates_windowEmulation();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -597,8 +656,6 @@ public String extractPattern(TemporalUnit unit) {
|
||||
switch ( unit ) {
|
||||
case DAY_OF_WEEK:
|
||||
return "(" + super.extractPattern(unit) + "+1)";
|
||||
case SECOND:
|
||||
return "(extract(second from ?2)+extract(microsecond from ?2)/1e6)";
|
||||
default:
|
||||
return super.extractPattern(unit);
|
||||
}
|
||||
@ -788,28 +845,28 @@ public String getReadLockString(String aliases, int timeout) {
|
||||
@Override
|
||||
public String getForUpdateNowaitString() {
|
||||
return supportsNoWait()
|
||||
? " for update nowait"
|
||||
? getForUpdateString() + " nowait"
|
||||
: getForUpdateString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getForUpdateNowaitString(String aliases) {
|
||||
return supportsNoWait()
|
||||
? " for update of " + aliases + " nowait"
|
||||
: getForUpdateString(aliases);
|
||||
? getForUpdateString( aliases ) + " nowait"
|
||||
: getForUpdateString( aliases );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getForUpdateSkipLockedString() {
|
||||
return supportsSkipLocked()
|
||||
? " for update skip locked"
|
||||
? getForUpdateString() + " skip locked"
|
||||
: getForUpdateString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getForUpdateSkipLockedString(String aliases) {
|
||||
return supportsSkipLocked()
|
||||
? " for update of " + aliases + " skip locked"
|
||||
? getForUpdateString( aliases ) + " skip locked"
|
||||
: getForUpdateString( aliases );
|
||||
}
|
||||
|
||||
@ -850,7 +907,8 @@ public boolean supportsWait() {
|
||||
|
||||
@Override
|
||||
public boolean supportsSkipLocked() {
|
||||
return getVersion().isSameOrAfter( 20, 1 );
|
||||
// See https://www.cockroachlabs.com/docs/stable/select-for-update.html#wait-policies
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -878,16 +936,78 @@ public IdentifierHelper buildIdentifierHelper(IdentifierHelperBuilder builder, D
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
|
||||
EntityMappingType rootEntityDescriptor,
|
||||
RuntimeModelCreationContext runtimeModelCreationContext) {
|
||||
return new CteMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
|
||||
public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() {
|
||||
return EXTRACTOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constraint-name extractor for Postgres constraint violation exceptions.
|
||||
* Originally contributed by Denny Bartelt.
|
||||
*/
|
||||
private static final ViolatedConstraintNameExtractor EXTRACTOR =
|
||||
new TemplatedViolatedConstraintNameExtractor( sqle -> {
|
||||
final String sqlState = JdbcExceptionHelper.extractSqlState( sqle );
|
||||
if ( sqlState == null ) {
|
||||
return null;
|
||||
}
|
||||
switch ( Integer.parseInt( sqlState ) ) {
|
||||
// CHECK VIOLATION
|
||||
case 23514:
|
||||
return extractUsingTemplate( "violates check constraint \"","\"", sqle.getMessage() );
|
||||
// UNIQUE VIOLATION
|
||||
case 23505:
|
||||
return extractUsingTemplate( "violates unique constraint \"","\"", sqle.getMessage() );
|
||||
// FOREIGN KEY VIOLATION
|
||||
case 23503:
|
||||
return extractUsingTemplate( "violates foreign key constraint \"","\"", sqle.getMessage() );
|
||||
// NOT NULL VIOLATION
|
||||
case 23502:
|
||||
return extractUsingTemplate( "null value in column \"","\" violates not-null constraint", sqle.getMessage() );
|
||||
// TODO: RESTRICT VIOLATION
|
||||
case 23001:
|
||||
return null;
|
||||
// ALL OTHER
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} );
|
||||
|
||||
@Override
|
||||
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
|
||||
EntityMappingType rootEntityDescriptor,
|
||||
RuntimeModelCreationContext runtimeModelCreationContext) {
|
||||
return new CteInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
|
||||
public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
|
||||
return (sqlException, message, sql) -> {
|
||||
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
|
||||
if ( sqlState == null ) {
|
||||
return null;
|
||||
}
|
||||
switch ( sqlState ) {
|
||||
case "40P01":
|
||||
// DEADLOCK DETECTED
|
||||
return new LockAcquisitionException( message, sqlException, sql);
|
||||
case "55P03":
|
||||
// LOCK NOT AVAILABLE
|
||||
return new PessimisticLockException( message, sqlException, sql);
|
||||
case "57014":
|
||||
return new QueryTimeoutException( message, sqlException, sql );
|
||||
default:
|
||||
// returning null allows other delegates to operate
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// CockroachDB doesn't support this by default. See sql.multiple_modifications_of_table.enabled
|
||||
//
|
||||
// @Override
|
||||
// public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
|
||||
// EntityMappingType rootEntityDescriptor,
|
||||
// RuntimeModelCreationContext runtimeModelCreationContext) {
|
||||
// return new CteMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
|
||||
// EntityMappingType rootEntityDescriptor,
|
||||
// RuntimeModelCreationContext runtimeModelCreationContext) {
|
||||
// return new CteInsertStrategy( rootEntityDescriptor, runtimeModelCreationContext );
|
||||
// }
|
||||
}
|
||||
|
@ -576,9 +576,7 @@ public JdbcType resolveSqlTypeDescriptor(
|
||||
if ( sqlTypeCode != null ) {
|
||||
return ( (ArrayJdbcType) jdbcType ).resolveType(
|
||||
jdbcTypeRegistry.getTypeConfiguration(),
|
||||
jdbcTypeRegistry.getTypeConfiguration().getServiceRegistry()
|
||||
.getService( JdbcServices.class )
|
||||
.getDialect(),
|
||||
this,
|
||||
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
|
||||
null
|
||||
);
|
||||
|
@ -41,7 +41,6 @@
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
|
||||
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
@ -310,9 +309,7 @@ public JdbcType resolveSqlTypeDescriptor(
|
||||
if ( sqlTypeCode != null ) {
|
||||
return ( (ArrayJdbcType) jdbcType ).resolveType(
|
||||
jdbcTypeRegistry.getTypeConfiguration(),
|
||||
jdbcTypeRegistry.getTypeConfiguration().getServiceRegistry()
|
||||
.getService( JdbcServices.class )
|
||||
.getDialect(),
|
||||
this,
|
||||
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
|
||||
null
|
||||
);
|
||||
|
@ -239,6 +239,20 @@ public void median_percentileCont(boolean over) {
|
||||
.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* CockroachDB lacks implicit casting: https://github.com/cockroachdb/cockroach/issues/89965
|
||||
*/
|
||||
public void median_percentileCont_castDouble() {
|
||||
functionRegistry.patternDescriptorBuilder(
|
||||
"median",
|
||||
"percentile_cont(0.5) within group (order by cast(?1 as double precision))"
|
||||
)
|
||||
.setInvariantType(doubleType)
|
||||
.setExactArgumentCount( 1 )
|
||||
.setParameterTypes(NUMERIC)
|
||||
.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning: the semantics of this function are inconsistent between DBs.
|
||||
*
|
||||
|
@ -8,10 +8,13 @@
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
|
||||
public class CockroachDBIdentityColumnSupport extends IdentityColumnSupportImpl {
|
||||
@Override
|
||||
public boolean supportsIdentityColumns() {
|
||||
// Full support requires setting the sql.defaults.serial_normalization=sql_sequence in CockroachDB.
|
||||
// Also, support for serial4 is not enabled by default: https://github.com/cockroachdb/cockroach/issues/26925#issuecomment-1255293916
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -23,9 +26,17 @@ public String getIdentitySelectString(String table, String column, int type) {
|
||||
|
||||
@Override
|
||||
public String getIdentityColumnString(int type) {
|
||||
return type == Types.SMALLINT ?
|
||||
"serial4 not null" :
|
||||
"serial8 not null";
|
||||
switch ( type ) {
|
||||
case Types.TINYINT:
|
||||
case Types.SMALLINT:
|
||||
return "serial2 not null";
|
||||
case Types.INTEGER:
|
||||
return "serial4 not null";
|
||||
case Types.BIGINT:
|
||||
return "serial8 not null";
|
||||
default:
|
||||
throw new MappingException( "illegal identity column type");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -101,10 +101,8 @@ public String getSqlTruncateCommand(
|
||||
Function<SharedSessionContractImplementor, String> sessionUidAccess,
|
||||
SharedSessionContractImplementor session) {
|
||||
if ( idTable.getSessionUidColumn() != null ) {
|
||||
assert sessionUidAccess != null;
|
||||
final String uid = sessionUidAccess.apply( session );
|
||||
return getTruncateTableCommand() + " " + idTable.getQualifiedTableName()
|
||||
+ " where " + idTable.getSessionUidColumn().getColumnName() + " = " + uid;
|
||||
+ " where " + idTable.getSessionUidColumn().getColumnName() + " = ?";
|
||||
}
|
||||
else {
|
||||
return getTruncateTableCommand() + " " + idTable.getQualifiedTableName();
|
||||
|
@ -7,6 +7,7 @@
|
||||
package org.hibernate.dialect.temptable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@ -24,6 +25,7 @@
|
||||
import org.hibernate.id.enhanced.Optimizer;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Contributable;
|
||||
@ -39,7 +41,10 @@
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.SingleTableEntityPersister;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
@ -70,12 +75,25 @@ private TemporaryTable(
|
||||
SqlStringGenerationContext sqlStringGenerationContext,
|
||||
Function<TemporaryTable, List<TemporaryTableColumn>> columnInitializer) {
|
||||
this.entityDescriptor = entityDescriptor;
|
||||
|
||||
final EntityPersister entityPersister = entityDescriptor.getEntityPersister();
|
||||
final EntityPersister rootEntityPersister = entityDescriptor.getRootEntityDescriptor().getEntityPersister();
|
||||
final String persisterQuerySpace = entityPersister.getSynchronizedQuerySpaces()[0];
|
||||
final QualifiedNameParser.NameParts nameParts = QualifiedNameParser.INSTANCE.parse( persisterQuerySpace );
|
||||
// The table name might be a sub-query, which is inappropriate for a temporary table name
|
||||
final String originalTableName = entityDescriptor.getEntityPersister().getSynchronizedQuerySpaces()[0];
|
||||
final QualifiedNameParser.NameParts nameParts = QualifiedNameParser.INSTANCE.parse( originalTableName );
|
||||
final String tableBaseName;
|
||||
if ( rootEntityPersister != entityPersister && rootEntityPersister instanceof SingleTableEntityPersister ) {
|
||||
// In this case, the descriptor is a subclass of a single table inheritance.
|
||||
// To avoid name collisions, we suffix the table name with the subclass number
|
||||
tableBaseName = nameParts.getObjectName().getText() + ArrayHelper.indexOf(
|
||||
( (SingleTableEntityPersister) rootEntityPersister ).getSubclassClosure(),
|
||||
entityPersister.getEntityName()
|
||||
);
|
||||
}
|
||||
else {
|
||||
tableBaseName = nameParts.getObjectName().getText();
|
||||
}
|
||||
final QualifiedNameParser.NameParts adjustedNameParts = QualifiedNameParser.INSTANCE.parse(
|
||||
temporaryTableNameAdjuster.apply( nameParts.getObjectName().getText() )
|
||||
temporaryTableNameAdjuster.apply( tableBaseName )
|
||||
);
|
||||
final String temporaryTableName = adjustedNameParts.getObjectName().getText();
|
||||
final Identifier tableNameIdentifier;
|
||||
@ -101,11 +119,12 @@ private TemporaryTable(
|
||||
);
|
||||
this.dialect = dialect;
|
||||
if ( dialect.getSupportedTemporaryTableKind() == TemporaryTableKind.PERSISTENT ) {
|
||||
final TypeConfiguration typeConfiguration = entityDescriptor.getEntityPersister()
|
||||
final TypeConfiguration typeConfiguration = entityPersister
|
||||
.getFactory()
|
||||
.getTypeConfiguration();
|
||||
final BasicType<UUID> uuidType = typeConfiguration
|
||||
.getBasicTypeForJavaType( UUID.class );
|
||||
final BasicType<UUID> uuidType = typeConfiguration.getBasicTypeRegistry().resolve(
|
||||
StandardBasicTypes.UUID_CHAR
|
||||
);
|
||||
this.sessionUidColumn = new TemporaryTableSessionUidColumn(
|
||||
this,
|
||||
uuidType,
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
package org.hibernate.query.sqm.mutation.internal.temptable;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
@ -127,7 +128,7 @@ public static int saveMatchingIdsIntoIdTable(
|
||||
jdbcPosition,
|
||||
jdbcPosition + 1,
|
||||
new QueryLiteral<>(
|
||||
sessionUidAccess.apply( executionContext.getSession() ),
|
||||
UUID.fromString( sessionUidAccess.apply( executionContext.getSession() ) ),
|
||||
(BasicValuedMapping) idTable.getSessionUidColumn().getJdbcMapping()
|
||||
)
|
||||
)
|
||||
@ -293,7 +294,7 @@ private static void applyIdTableRestrictions(
|
||||
),
|
||||
ComparisonOperator.EQUAL,
|
||||
new QueryLiteral<>(
|
||||
sessionUidAccess.apply( executionContext.getSession() ),
|
||||
UUID.fromString( sessionUidAccess.apply( executionContext.getSession() ) ),
|
||||
(BasicValuedMapping) idTable.getSessionUidColumn().getJdbcMapping()
|
||||
)
|
||||
)
|
||||
|
@ -13,6 +13,7 @@
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.dialect.temptable.TemporaryTable;
|
||||
@ -55,6 +56,7 @@
|
||||
import org.hibernate.sql.ast.tree.from.UnionTableReference;
|
||||
import org.hibernate.sql.ast.tree.insert.InsertStatement;
|
||||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.ast.tree.select.SortSpecification;
|
||||
@ -90,6 +92,7 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
|
||||
private final EntityMappingType entityDescriptor;
|
||||
|
||||
private final JdbcParameterBindings jdbcParameterBindings;
|
||||
private final JdbcParameter sessionUidParameter;
|
||||
|
||||
private final Map<TableReference, List<Assignment>> assignmentsByTable;
|
||||
private final Map<SqmParameter<?>, MappingModelExpressible<?>> paramTypeResolutions;
|
||||
@ -107,6 +110,7 @@ public InsertExecutionDelegate(
|
||||
List<Assignment> assignments,
|
||||
InsertStatement insertStatement,
|
||||
Map<SqmParameter<?>, List<List<JdbcParameter>>> parameterResolutions,
|
||||
JdbcParameter sessionUidParameter,
|
||||
Map<SqmParameter<?>, MappingModelExpressible<?>> paramTypeResolutions,
|
||||
DomainQueryExecutionContext executionContext) {
|
||||
this.sqmInsert = sqmInsert;
|
||||
@ -116,6 +120,7 @@ public InsertExecutionDelegate(
|
||||
this.sessionUidAccess = sessionUidAccess;
|
||||
this.domainParameterXref = domainParameterXref;
|
||||
this.updatingTableGroup = insertingTableGroup;
|
||||
this.sessionUidParameter = sessionUidParameter;
|
||||
this.paramTypeResolutions = paramTypeResolutions;
|
||||
this.insertStatement = insertStatement;
|
||||
|
||||
@ -189,6 +194,15 @@ public int execute(ExecutionContext executionContext) {
|
||||
);
|
||||
|
||||
try {
|
||||
if ( sessionUidParameter != null ) {
|
||||
jdbcParameterBindings.addBinding(
|
||||
sessionUidParameter,
|
||||
new JdbcParameterBindingImpl(
|
||||
entityTable.getSessionUidColumn().getJdbcMapping(),
|
||||
UUID.fromString( sessionUidAccess.apply( executionContext.getSession() ) )
|
||||
)
|
||||
);
|
||||
}
|
||||
final int rows = ExecuteWithTemporaryTableHelper.saveIntoTemporaryTable(
|
||||
insertStatement,
|
||||
jdbcParameterBindings,
|
||||
@ -422,24 +436,53 @@ private void insertRootTable(
|
||||
rootIdentity
|
||||
)
|
||||
);
|
||||
final TemporaryTableColumn rowNumberColumn = entityTable.getColumns().get(
|
||||
entityTable.getColumns().size() - 1
|
||||
);
|
||||
final TemporaryTableColumn rowNumberColumn;
|
||||
final TemporaryTableColumn sessionUidColumn;
|
||||
final Predicate sessionUidPredicate;
|
||||
if ( entityTable.getSessionUidColumn() == null ) {
|
||||
rowNumberColumn = entityTable.getColumns().get(
|
||||
entityTable.getColumns().size() - 1
|
||||
);
|
||||
sessionUidColumn = null;
|
||||
sessionUidPredicate = null;
|
||||
}
|
||||
else {
|
||||
rowNumberColumn = entityTable.getColumns().get(
|
||||
entityTable.getColumns().size() - 2
|
||||
);
|
||||
sessionUidColumn = entityTable.getSessionUidColumn();
|
||||
sessionUidPredicate = new ComparisonPredicate(
|
||||
new ColumnReference(
|
||||
(String) null,
|
||||
sessionUidColumn.getColumnName(),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
sessionUidColumn.getJdbcMapping(),
|
||||
sessionFactory
|
||||
),
|
||||
ComparisonOperator.EQUAL,
|
||||
sessionUidParameter
|
||||
);
|
||||
}
|
||||
final UpdateStatement updateStatement = new UpdateStatement(
|
||||
temporaryTableReference,
|
||||
temporaryTableAssignments,
|
||||
new ComparisonPredicate(
|
||||
new ColumnReference(
|
||||
(String) null,
|
||||
rowNumberColumn.getColumnName(),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
rowNumberColumn.getJdbcMapping(),
|
||||
sessionFactory
|
||||
),
|
||||
ComparisonOperator.EQUAL,
|
||||
rowNumber
|
||||
Predicate.combinePredicates(
|
||||
new ComparisonPredicate(
|
||||
new ColumnReference(
|
||||
(String) null,
|
||||
rowNumberColumn.getColumnName(),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
rowNumberColumn.getJdbcMapping(),
|
||||
sessionFactory
|
||||
),
|
||||
ComparisonOperator.EQUAL,
|
||||
rowNumber
|
||||
),
|
||||
sessionUidPredicate
|
||||
)
|
||||
);
|
||||
|
||||
@ -448,6 +491,15 @@ private void insertRootTable(
|
||||
.buildUpdateTranslator( sessionFactory, updateStatement )
|
||||
.translate( null, executionContext.getQueryOptions() );
|
||||
final JdbcParameterBindings updateBindings = new JdbcParameterBindingsImpl( 2 );
|
||||
if ( sessionUidColumn != null ) {
|
||||
updateBindings.addBinding(
|
||||
sessionUidParameter,
|
||||
new JdbcParameterBindingImpl(
|
||||
sessionUidColumn.getJdbcMapping(),
|
||||
UUID.fromString( sessionUidAccess.apply( executionContext.getSession() ) )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
for ( int i = 0; i < rows; i++ ) {
|
||||
updateBindings.addBinding(
|
||||
|
@ -108,7 +108,7 @@ public void release(
|
||||
|
||||
released = true;
|
||||
|
||||
if ( created ) {
|
||||
if ( !created ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
import org.hibernate.dialect.temptable.TemporaryTable;
|
||||
import org.hibernate.dialect.temptable.TemporaryTableColumn;
|
||||
import org.hibernate.dialect.temptable.TemporaryTableSessionUidColumn;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
@ -51,6 +52,7 @@
|
||||
import org.hibernate.sql.ast.tree.insert.Values;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.update.Assignment;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||
import org.hibernate.type.BasicType;
|
||||
@ -74,6 +76,7 @@ public interface ExecutionDelegate {
|
||||
private final AfterUseAction afterUseAction;
|
||||
private final Function<SharedSessionContractImplementor,String> sessionUidAccess;
|
||||
private final DomainParameterXref domainParameterXref;
|
||||
private final JdbcParameter sessionUidParameter;
|
||||
|
||||
private final EntityPersister entityDescriptor;
|
||||
|
||||
@ -93,6 +96,14 @@ public interface ExecutionDelegate {
|
||||
|
||||
final String targetEntityName = sqmInsert.getTarget().getEntityName();
|
||||
this.entityDescriptor = sessionFactory.getRuntimeMetamodels().getMappingMetamodel().getEntityDescriptor( targetEntityName );
|
||||
|
||||
final TemporaryTableSessionUidColumn sessionUidColumn = entityTable.getSessionUidColumn();
|
||||
if ( sessionUidColumn == null ) {
|
||||
this.sessionUidParameter = null;
|
||||
}
|
||||
else {
|
||||
this.sessionUidParameter = new JdbcParameterImpl( sessionUidColumn.getJdbcMapping() );
|
||||
}
|
||||
}
|
||||
|
||||
public SqmInsertStatement<?> getSqmInsertStatement() {
|
||||
@ -173,13 +184,14 @@ private ExecutionDelegate resolveDelegate(DomainQueryExecutionContext executionC
|
||||
// visit the where-clause using our special converter, collecting information
|
||||
// about the restrictions
|
||||
|
||||
final TemporaryTableSessionUidColumn sessionUidColumn = entityTable.getSessionUidColumn();
|
||||
if ( sqmInsertStatement instanceof SqmInsertSelectStatement ) {
|
||||
final QueryPart queryPart = converterDelegate.visitQueryPart( ( (SqmInsertSelectStatement<?>) sqmInsertStatement ).getSelectQueryPart() );
|
||||
queryPart.visitQuerySpecs(
|
||||
querySpec -> {
|
||||
if ( additionalInsertValues.applySelections( querySpec, sessionFactory ) ) {
|
||||
final TemporaryTableColumn rowNumberColumn = entityTable.getColumns()
|
||||
.get( entityTable.getColumns().size() - 1 );
|
||||
.get( entityTable.getColumns().size() - ( sessionUidColumn == null ? 1 : 2 ) );
|
||||
final ColumnReference columnReference = new ColumnReference(
|
||||
(String) null,
|
||||
rowNumberColumn.getColumnName(),
|
||||
@ -205,7 +217,7 @@ else if ( entityDescriptor.getIdentifierGenerator() instanceof OptimizableGenera
|
||||
return;
|
||||
}
|
||||
final TemporaryTableColumn rowNumberColumn = entityTable.getColumns()
|
||||
.get( entityTable.getColumns().size() - 1 );
|
||||
.get( entityTable.getColumns().size() - ( sessionUidColumn == null ? 1 : 2 ) );
|
||||
final ColumnReference columnReference = new ColumnReference(
|
||||
(String) null,
|
||||
rowNumberColumn.getColumnName(),
|
||||
@ -229,6 +241,30 @@ else if ( entityDescriptor.getIdentifierGenerator() instanceof OptimizableGenera
|
||||
);
|
||||
}
|
||||
}
|
||||
if ( sessionUidColumn != null ) {
|
||||
final ColumnReference sessionUidColumnReference = new ColumnReference(
|
||||
(String) null,
|
||||
sessionUidColumn.getColumnName(),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
sessionUidColumn.getJdbcMapping(),
|
||||
sessionFactory
|
||||
);
|
||||
insertStatement.getTargetColumnReferences().add(
|
||||
sessionUidColumnReference
|
||||
);
|
||||
targetPathColumns.add(
|
||||
new Assignment( sessionUidColumnReference, sessionUidParameter )
|
||||
);
|
||||
querySpec.getSelectClause().addSqlSelection(
|
||||
new SqlSelectionImpl(
|
||||
insertStatement.getTargetColumnReferences().size(),
|
||||
insertStatement.getTargetColumnReferences().size() - 1,
|
||||
sessionUidParameter
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
insertStatement.setSourceSelectStatement( queryPart );
|
||||
@ -262,6 +298,23 @@ else if ( entityDescriptor.getIdentifierGenerator() instanceof OptimizableGenera
|
||||
else {
|
||||
rowNumberType = null;
|
||||
}
|
||||
if ( sessionUidColumn != null ) {
|
||||
final ColumnReference sessionUidColumnReference = new ColumnReference(
|
||||
(String) null,
|
||||
sessionUidColumn.getColumnName(),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
sessionUidColumn.getJdbcMapping(),
|
||||
sessionFactory
|
||||
);
|
||||
insertStatement.getTargetColumnReferences().add(
|
||||
sessionUidColumnReference
|
||||
);
|
||||
targetPathColumns.add(
|
||||
new Assignment( sessionUidColumnReference, sessionUidParameter )
|
||||
);
|
||||
}
|
||||
final List<SqmValues> sqmValuesList = ( (SqmInsertValuesStatement<?>) sqmInsertStatement ).getValuesList();
|
||||
final List<Values> valuesList = new ArrayList<>( sqmValuesList.size() );
|
||||
for ( int i = 0; i < sqmValuesList.size(); i++ ) {
|
||||
@ -275,6 +328,9 @@ else if ( entityDescriptor.getIdentifierGenerator() instanceof OptimizableGenera
|
||||
)
|
||||
);
|
||||
}
|
||||
if ( sessionUidParameter != null ) {
|
||||
values.getExpressions().add( sessionUidParameter );
|
||||
}
|
||||
valuesList.add( values );
|
||||
}
|
||||
insertStatement.setValuesList( valuesList );
|
||||
@ -303,6 +359,7 @@ else if ( entityDescriptor.getIdentifierGenerator() instanceof OptimizableGenera
|
||||
targetPathColumns,
|
||||
insertStatement,
|
||||
parameterResolutions,
|
||||
sessionUidParameter,
|
||||
paramTypeResolutions,
|
||||
executionContext
|
||||
);
|
||||
|
@ -107,6 +107,7 @@ public void release() {
|
||||
catch (Throwable t2) {
|
||||
suppressed = t2;
|
||||
}
|
||||
jdbcConnection = null;
|
||||
if ( suppressed != null ) {
|
||||
if ( originalException == null ) {
|
||||
originalException = suppressed;
|
||||
|
@ -19,6 +19,7 @@
|
||||
import org.hibernate.id.SequenceMismatchStrategy;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
@ -27,6 +28,7 @@
|
||||
* Verifies that setting {@code AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY} to {@code none}
|
||||
* is going to skip loading the sequence information from the database.
|
||||
*/
|
||||
@RequiresDialect( H2Dialect.class )
|
||||
@TestForIssue( jiraKey = "HHH-14667")
|
||||
public class SkipLoadingSequenceInformationTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
|
@ -76,17 +76,17 @@ private void tryBuildingSessionFactory(Class... annotatedClasses) {
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Entity(name = "Building1")
|
||||
@DiscriminatorValue(DISCRIMINATOR_VALUE) // Duplicated discriminator value in single hierarchy.
|
||||
public static class Building1 extends Building {
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Entity(name = "Building2")
|
||||
@DiscriminatorValue(DISCRIMINATOR_VALUE) // Duplicated discriminator value in single hierarchy.
|
||||
public static class Building2 extends Building {
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Entity(name = "Furniture")
|
||||
@DiscriminatorColumn(name = "entity_type")
|
||||
@DiscriminatorValue("F")
|
||||
public static class Furniture {
|
||||
@ -95,7 +95,7 @@ public static class Furniture {
|
||||
private Integer id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Entity(name = "Chair")
|
||||
@DiscriminatorValue(DISCRIMINATOR_VALUE) // Duplicated discriminator value in different hierarchy.
|
||||
public static class Chair extends Furniture {
|
||||
}
|
||||
|
@ -43,6 +43,7 @@
|
||||
import org.hibernate.persister.entity.AbstractEntityPersister;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableStrategy;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
import org.hibernate.tool.schema.TargetType;
|
||||
@ -267,6 +268,7 @@ private StandardServiceRegistry createStandardServiceRegistry(String defaultCata
|
||||
final BootstrapServiceRegistry bsr = bsrb.build();
|
||||
|
||||
final Map<String, Object> settings = new HashMap<>();
|
||||
settings.put( PersistentTableStrategy.DROP_ID_TABLES, "true" );
|
||||
settings.put( GlobalTemporaryTableStrategy.DROP_ID_TABLES, "true" );
|
||||
settings.put( LocalTemporaryTableStrategy.DROP_ID_TABLES, "true" );
|
||||
if ( !Environment.getProperties().containsKey( Environment.CONNECTION_PROVIDER ) ) {
|
||||
|
@ -26,6 +26,8 @@
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.hibernate.testing.DialectChecks;
|
||||
import org.hibernate.testing.RequiresDialectFeature;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@ -34,6 +36,7 @@
|
||||
*/
|
||||
@RunWith(BytecodeEnhancerRunner.class)
|
||||
@CustomEnhancementContext({ DirtyCheckEnhancementContext.class })
|
||||
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
|
||||
public class DirtyCheckPrivateUnMappedCollectionTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
boolean skipTest;
|
||||
|
@ -92,7 +92,7 @@ protected void addSettings(Map<String,Object> settings) {
|
||||
settings.put( Environment.USE_SCROLLABLE_RESULTSET, "" + supportsScroll );
|
||||
}
|
||||
finally {
|
||||
connection.close();
|
||||
cp.closeConnection( connection );
|
||||
}
|
||||
}
|
||||
catch (SQLException ignore) {
|
||||
|
@ -529,7 +529,7 @@ public static class Company extends AbstractCompany {
|
||||
public CompanyInfo info;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Entity(name = "PlanItem")
|
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
public abstract class PlanItem {
|
||||
|
||||
@ -546,7 +546,7 @@ public void setId(Integer id) {
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Entity(name = "Task")
|
||||
@SecondaryTable( name = "Task" )
|
||||
public class Task extends PlanItem {
|
||||
@Id
|
||||
|
@ -19,6 +19,7 @@
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.annotations.ParamDef;
|
||||
import org.hibernate.dialect.AbstractHANADialect;
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.dialect.DerbyDialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
@ -79,6 +80,7 @@ public void testYesNo(SessionFactoryScope scope) {
|
||||
@SkipForDialect(dialectClass = TiDBDialect.class, reason = "TiDB silently converts a boolean to string types")
|
||||
@SkipForDialect(dialectClass = SybaseDialect.class, matchSubTypes = true, reason = "Sybase silently converts a boolean to string types")
|
||||
@SkipForDialect(dialectClass = AbstractHANADialect.class, matchSubTypes = true, reason = "HANA silently converts a boolean to string types")
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, matchSubTypes = true, reason = "Cockroach silently converts a boolean to string types")
|
||||
public void testYesNoMismatch(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
final EntityOne loaded = session.byId( EntityOne.class ).load( 1 );
|
||||
|
@ -19,6 +19,7 @@
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.id.enhanced.HiLoOptimizer;
|
||||
import org.hibernate.id.enhanced.Optimizer;
|
||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||
@ -65,30 +66,48 @@ public void dropDatabaseSequence(SessionFactoryScope scope) {
|
||||
final ConnectionProvider connectionProvider = scope.getSessionFactory()
|
||||
.getServiceRegistry()
|
||||
.getService( ConnectionProvider.class );
|
||||
scope.inSession(
|
||||
session -> {
|
||||
Connection connection = null;
|
||||
final JdbcConnectionAccess jdbcConnectionAccess = session.getJdbcConnectionAccess();
|
||||
try {
|
||||
connection = jdbcConnectionAccess.obtainConnection();
|
||||
try ( Statement statement = connection.createStatement() ) {
|
||||
|
||||
try ( Connection connection = connectionProvider.getConnection();
|
||||
Statement statement = connection.createStatement() ) {
|
||||
for ( String dropSequenceStatement : dropSequenceStatements ) {
|
||||
try {
|
||||
statement.execute( dropSequenceStatement );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
System.out.printf( "TEST DEBUG : dropping sequence failed [`%s`] - %s", dropSequenceStatement, e.getMessage() );
|
||||
System.out.println();
|
||||
e.printStackTrace( System.out );
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
// Commit in between because CockroachDB fails to drop and commit schema objects in the same transaction
|
||||
connection.commit();
|
||||
|
||||
for ( String dropSequenceStatement : dropSequenceStatements ) {
|
||||
try {
|
||||
statement.execute( dropSequenceStatement );
|
||||
for ( String createSequenceStatement : createSequenceStatements ) {
|
||||
statement.execute( createSequenceStatement );
|
||||
}
|
||||
connection.commit();
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
fail( e.getMessage() );
|
||||
}
|
||||
finally {
|
||||
if ( connection != null ) {
|
||||
try {
|
||||
jdbcConnectionAccess.releaseConnection( connection );
|
||||
}
|
||||
catch (SQLException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
System.out.printf( "TEST DEBUG : dropping sequence failed [`%s`] - %s", dropSequenceStatement, e.getMessage() );
|
||||
System.out.println();
|
||||
e.printStackTrace( System.out );
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
for ( String createSequenceStatement : createSequenceStatements ) {
|
||||
statement.execute( createSequenceStatement );
|
||||
}
|
||||
connection.commit();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
fail( e.getMessage() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -31,6 +31,7 @@
|
||||
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableStrategy;
|
||||
|
||||
import org.hibernate.testing.jdbc.SharedDriverManagerConnectionProviderImpl;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
@ -227,6 +228,7 @@ protected Map getConfig() {
|
||||
config.put( AvailableSettings.ORM_XML_FILES, dds );
|
||||
}
|
||||
|
||||
config.put( PersistentTableStrategy.DROP_ID_TABLES, "true" );
|
||||
config.put( GlobalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
config.put( LocalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
if ( !config.containsKey( Environment.CONNECTION_PROVIDER ) ) {
|
||||
|
@ -6,8 +6,11 @@
|
||||
*/
|
||||
package org.hibernate.orm.test.jpa.compliance;
|
||||
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
|
||||
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Jpa;
|
||||
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -44,6 +47,7 @@ public void tearDown(EntityManagerFactoryScope scope) {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "https://github.com/cockroachdb/cockroach/issues/82478")
|
||||
public void testCriteriaMod(EntityManagerFactoryScope scope) {
|
||||
scope.inEntityManager(
|
||||
entityManager -> {
|
||||
|
@ -19,8 +19,10 @@
|
||||
import org.hibernate.graph.GraphParser;
|
||||
import org.hibernate.graph.GraphSemantic;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Jpa;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -44,6 +46,7 @@
|
||||
FetchGraphTest.Trigger.class,
|
||||
FetchGraphTest.FinanceEntity.class
|
||||
})
|
||||
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class)
|
||||
public class FetchGraphTest {
|
||||
|
||||
@BeforeEach
|
||||
|
@ -11,12 +11,14 @@
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.orm.test.jpa.model.AbstractJPATest;
|
||||
import org.hibernate.orm.test.jpa.model.Item;
|
||||
import org.hibernate.orm.test.jpa.model.MyEntity;
|
||||
|
||||
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||
import org.hibernate.testing.jdbc.SQLServerSnapshotIsolationConnectionProvider;
|
||||
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||
@ -82,6 +84,7 @@ protected void tearDown() {
|
||||
* EJB3 LockModeType.READ actually maps to the Hibernate LockMode.OPTIMISTIC
|
||||
*/
|
||||
@Test
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "Cockroach uses SERIALIZABLE by default and fails to acquire a write lock after a TX in between committed changes to a row")
|
||||
public void testLockModeTypeRead() {
|
||||
if ( !readCommittedIsolationMaintained( "ejb3 lock tests" ) ) {
|
||||
return;
|
||||
@ -176,6 +179,7 @@ public void testLockModeTypeRead() {
|
||||
* lock(entity, LockModeType.WRITE) on non-versioned objects will not be portable.
|
||||
*/
|
||||
@Test
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "Cockroach uses SERIALIZABLE by default and fails to acquire a write lock after a TX in between committed changes to a row")
|
||||
public void testLockModeTypeWrite() {
|
||||
if ( !readCommittedIsolationMaintained( "ejb3 lock tests" ) ) {
|
||||
return;
|
||||
|
@ -11,6 +11,7 @@
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.orm.test.jpa.model.AbstractJPATest;
|
||||
@ -20,6 +21,7 @@
|
||||
import org.hibernate.testing.jdbc.SQLServerSnapshotIsolationConnectionProvider;
|
||||
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||
import org.hibernate.testing.transaction.TransactionUtil2;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -55,6 +57,7 @@ protected void tearDown() {
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-8786" )
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
public void testLockTimeoutFind() {
|
||||
final Item item = new Item( "find" );
|
||||
|
||||
@ -95,6 +98,7 @@ public void testLockTimeoutFind() {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "Cockroach uses SERIALIZABLE by default and seems to fail reading a row that is exclusively locked by a different TX")
|
||||
public void testLockTimeoutRefresh() {
|
||||
final Item item = new Item( "refresh" );
|
||||
|
||||
@ -136,6 +140,7 @@ public void testLockTimeoutRefresh() {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "Cockroach uses SERIALIZABLE by default and seems to fail reading a row that is exclusively locked by a different TX")
|
||||
public void testLockTimeoutLock() {
|
||||
final Item item = new Item( "lock" );
|
||||
|
||||
|
@ -99,6 +99,7 @@ public void testFindWithTimeoutHint() {
|
||||
@RequiresDialectFeature( value = DialectChecks.SupportsLockTimeouts.class,
|
||||
comment = "Test verifies proper exception throwing when a lock timeout is specified.",
|
||||
jiraKey = "HHH-7252" )
|
||||
@SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
public void testFindWithPessimisticWriteLockTimeoutException() {
|
||||
Lock lock = new Lock();
|
||||
lock.setName( "name" );
|
||||
@ -146,6 +147,7 @@ public void testFindWithPessimisticWriteLockTimeoutException() {
|
||||
@RequiresDialectFeature( value = DialectChecks.SupportsLockTimeouts.class,
|
||||
comment = "Test verifies proper exception throwing when a lock timeout is specified for Query#getSingleResult.",
|
||||
jiraKey = "HHH-13364" )
|
||||
@SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
public void testQuerySingleResultPessimisticWriteLockTimeoutException() {
|
||||
Lock lock = new Lock();
|
||||
lock.setName( "name" );
|
||||
@ -190,6 +192,7 @@ public void testQuerySingleResultPessimisticWriteLockTimeoutException() {
|
||||
@RequiresDialectFeature( value = DialectChecks.SupportsLockTimeouts.class,
|
||||
comment = "Test verifies proper exception throwing when a lock timeout is specified for Query#getResultList.",
|
||||
jiraKey = "HHH-13364" )
|
||||
@SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
public void testQueryResultListPessimisticWriteLockTimeoutException() {
|
||||
Lock lock = new Lock();
|
||||
lock.setName( "name" );
|
||||
@ -237,6 +240,7 @@ public void testQueryResultListPessimisticWriteLockTimeoutException() {
|
||||
@RequiresDialectFeature( value = DialectChecks.SupportsLockTimeouts.class,
|
||||
comment = "Test verifies proper exception throwing when a lock timeout is specified for NamedQuery#getResultList.",
|
||||
jiraKey = "HHH-13364" )
|
||||
@SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
public void testNamedQueryResultListPessimisticWriteLockTimeoutException() {
|
||||
Lock lock = new Lock();
|
||||
lock.setName( "name" );
|
||||
@ -278,6 +282,7 @@ public void testNamedQueryResultListPessimisticWriteLockTimeoutException() {
|
||||
|
||||
@Test
|
||||
@RequiresDialectFeature( value = DialectChecks.SupportSkipLocked.class )
|
||||
@SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
public void testUpdateWithPessimisticReadLockSkipLocked() {
|
||||
Lock lock = new Lock();
|
||||
lock.setName( "name" );
|
||||
@ -323,6 +328,7 @@ public void testUpdateWithPessimisticReadLockSkipLocked() {
|
||||
|
||||
@Test
|
||||
@RequiresDialectFeature(value = DialectChecks.SupportsLockTimeouts.class)
|
||||
@SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
public void testUpdateWithPessimisticReadLockWithoutNoWait() {
|
||||
Lock lock = new Lock();
|
||||
lock.setName( "name" );
|
||||
@ -1168,6 +1174,7 @@ public void testLockTimeoutEMProps() throws Exception {
|
||||
}, strictMatching = true, comment = "With InnoDB, a FK constraint check acquires a shared lock that isn't compatible with an exclusive lock")
|
||||
@SkipForDialect(value = HSQLDialect.class, comment = "Seems like FK constraint checks are not compatible with exclusive locks")
|
||||
@SkipForDialect(value = AbstractHANADialect.class, comment = "Seems like FK constraint checks are not compatible with exclusive locks")
|
||||
@SkipForDialect(value = CockroachDialect.class, comment = "Cockroach supports the 'for no key update' syntax but it doesn't work")
|
||||
public void testLockInsertFkTarget() {
|
||||
Lock lock = new Lock();
|
||||
lock.setName( "name" );
|
||||
@ -1204,6 +1211,7 @@ public void testLockInsertFkTarget() {
|
||||
}, strictMatching = true, comment = "With InnoDB, a FK constraint check acquires a shared lock that isn't compatible with an exclusive lock")
|
||||
@SkipForDialect(value = HSQLDialect.class, comment = "Seems like FK constraint checks are not compatible with exclusive locks")
|
||||
@SkipForDialect(value = AbstractHANADialect.class, comment = "Seems like FK constraint checks are not compatible with exclusive locks")
|
||||
@SkipForDialect(value = CockroachDialect.class, comment = "Cockroach supports the 'for no key update' syntax but it doesn't work")
|
||||
public void testLockUpdateFkTarget() {
|
||||
Lock lock1 = new Lock();
|
||||
lock1.setName( "l1" );
|
||||
|
@ -12,6 +12,7 @@
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.exception.SQLGrammarException;
|
||||
@ -19,6 +20,7 @@
|
||||
import org.hibernate.orm.test.jpa.model.Item;
|
||||
import org.hibernate.orm.test.jpa.model.Part;
|
||||
|
||||
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||
import org.hibernate.testing.jdbc.SQLServerSnapshotIsolationConnectionProvider;
|
||||
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||
@ -103,6 +105,7 @@ public void testStaleVersionedInstanceFoundInQueryResult() {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "Cockroach uses SERIALIZABLE by default and fails to acquire a write lock after a TX in between committed changes to a row")
|
||||
public void testStaleVersionedInstanceFoundOnLock() {
|
||||
if ( !readCommittedIsolationMaintained( "repeatable read tests" ) ) {
|
||||
return;
|
||||
@ -224,6 +227,7 @@ public void testStaleNonVersionedInstanceFoundInQueryResult() {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "Cockroach uses SERIALIZABLE by default and fails to acquire a write lock after a TX in between committed changes to a row")
|
||||
public void testStaleNonVersionedInstanceFoundOnLock() {
|
||||
if ( !readCommittedIsolationMaintained( "repeatable read tests" ) ) {
|
||||
return;
|
||||
|
@ -33,6 +33,7 @@
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@RequiresDialectFeature({DialectChecks.SupportsJdbcDriverProxying.class, DialectChecks.SupportsLockTimeouts.class})
|
||||
@SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
public class StatementIsClosedAfterALockExceptionTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
private static final PreparedStatementSpyConnectionProvider CONNECTION_PROVIDER = new PreparedStatementSpyConnectionProvider( false, false );
|
||||
@ -68,7 +69,6 @@ public void releaseResources() {
|
||||
|
||||
@Test(timeout = 1000 * 30) //30 seconds
|
||||
@TestForIssue(jiraKey = "HHH-11617")
|
||||
@SkipForDialect( value = CockroachDialect.class )
|
||||
public void testStatementIsClosed() {
|
||||
|
||||
TransactionUtil.doInJPA( this::entityManagerFactory, em1 -> {
|
||||
|
@ -26,6 +26,7 @@
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.AbstractHANADialect;
|
||||
import org.hibernate.dialect.AbstractTransactSQLDialect;
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.dialect.DerbyDialect;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
@ -125,6 +126,7 @@ public void bitType() {
|
||||
|
||||
@Test
|
||||
@SkipForDialect(value = PostgreSQLDialect.class, comment = "Turns tinyints into shorts in result sets and advertises the type as short in the metadata")
|
||||
@SkipForDialect(value = CockroachDialect.class, comment = "Turns tinyints into shorts in result sets and advertises the type as short in the metadata")
|
||||
@SkipForDialect(value = DerbyDialect.class, comment = "No support for the tinyint datatype so we use smallint")
|
||||
@SkipForDialect(value = DB2Dialect.class, comment = "No support for the tinyint datatype so we use smallint")
|
||||
@SkipForDialect(value = AbstractTransactSQLDialect.class, comment = "No support for the tinyint datatype so we use smallint")
|
||||
|
@ -35,6 +35,7 @@
|
||||
import org.hibernate.testing.orm.junit.Setting;
|
||||
import org.hibernate.testing.orm.junit.SettingProvider;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
@ -66,6 +67,14 @@
|
||||
)
|
||||
public class CloseEntityManagerWithActiveTransactionTest {
|
||||
|
||||
@BeforeAll
|
||||
public void beforeAll(EntityManagerFactoryScope scope) throws Exception {
|
||||
// This makes sure that hbm2ddl runs before we start a transaction for a test
|
||||
// This is important for database that only support SNAPSHOT/SERIALIZABLE isolation,
|
||||
// because a test transaction still sees the state before the DDL executed
|
||||
scope.getEntityManagerFactory();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown(EntityManagerFactoryScope scope) throws Exception {
|
||||
TransactionManager transactionManager = TestingJtaPlatformImpl.INSTANCE.getTransactionManager();
|
||||
|
@ -41,7 +41,8 @@
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-11477")
|
||||
@RequiresDialects({ @RequiresDialect(PostgreSQLDialect.class), @RequiresDialect(CockroachDialect.class) })
|
||||
// Note that Cockroach doesn't support LOB functions. See https://github.com/cockroachdb/cockroach/issues/26725
|
||||
@RequiresDialect(PostgreSQLDialect.class)
|
||||
@DomainModel(
|
||||
annotatedClasses = LobStringTest.TestEntity.class
|
||||
)
|
||||
|
@ -81,6 +81,7 @@ public void prepareTest() throws Exception {
|
||||
|
||||
@Test
|
||||
@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsLockTimeouts.class )
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
@SuppressWarnings( {"deprecation"})
|
||||
public void testLoading() {
|
||||
// open a session, begin a transaction and lock row
|
||||
@ -97,6 +98,7 @@ public void testLoading() {
|
||||
|
||||
@Test
|
||||
@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsLockTimeouts.class )
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
public void testCriteria() {
|
||||
// open a session, begin a transaction and lock row
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
@ -119,6 +121,7 @@ public void testCriteria() {
|
||||
|
||||
@Test
|
||||
@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsLockTimeouts.class )
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
public void testCriteriaAliasSpecific() {
|
||||
// open a session, begin a transaction and lock row
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
@ -143,6 +146,7 @@ public void testCriteriaAliasSpecific() {
|
||||
|
||||
@Test
|
||||
@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsLockTimeouts.class )
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995")
|
||||
public void testQuery() {
|
||||
// open a session, begin a transaction and lock row
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
@ -278,19 +282,12 @@ private void nowAttemptToUpdateRow() {
|
||||
executeSync( () -> doInHibernate( this::sessionFactory, _session -> {
|
||||
TransactionUtil.setJdbcTimeout( _session );
|
||||
try {
|
||||
// We used to load with write lock here to deal with databases that block (wait indefinitely)
|
||||
// direct attempts to write a locked row.
|
||||
// At some point, due to a bug, the lock mode was lost when applied via lock options, leading
|
||||
// this code to not apply the pessimistic write lock.
|
||||
// See HHH-12847 + https://github.com/hibernate/hibernate-orm/commit/719e5d0c12a6ef709bee907b8b651d27b8b08a6a.
|
||||
// At least Sybase waits indefinitely when really applying a PESSIMISTIC_WRITE lock here (and
|
||||
// the NO_WAIT part is not applied by the Sybase dialect so it doesn't help).
|
||||
// For now going back to LockMode.NONE as it's the lock mode that has been applied for quite
|
||||
// some time and it seems our supported databases don't have a problem with it.
|
||||
// load with write lock to deal with databases that block (wait indefinitely) direct attempts
|
||||
// to write a locked row
|
||||
A it = _session.get(
|
||||
A.class,
|
||||
id,
|
||||
new LockOptions( LockMode.NONE ).setTimeOut( LockOptions.NO_WAIT )
|
||||
new LockOptions( LockMode.PESSIMISTIC_WRITE ).setTimeOut( LockOptions.NO_WAIT )
|
||||
);
|
||||
_session.createNativeQuery( updateStatement() )
|
||||
.setParameter( "value", "changed" )
|
||||
|
@ -81,10 +81,7 @@ public void setUp() {
|
||||
connectionProvider = ConnectionProviderBuilder.buildConnectionProvider();
|
||||
|
||||
final GenerationTargetToDatabase target = new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
connectionProvider
|
||||
)
|
||||
new DdlTransactionIsolatorTestingImpl( tool.resolveJdbcContext( settings ) )
|
||||
);
|
||||
|
||||
|
||||
@ -104,8 +101,6 @@ public void setUp() {
|
||||
target
|
||||
);
|
||||
|
||||
target.release();
|
||||
|
||||
final SessionFactoryBuilder sfb = metadata.getSessionFactoryBuilder();
|
||||
sessionFactory = (SessionFactoryImplementor) sfb.build();
|
||||
currentTenantResolver.setHibernateBooted();
|
||||
|
@ -77,26 +77,23 @@ public void setUp() {
|
||||
HibernateSchemaManagementTool tool = new HibernateSchemaManagementTool();
|
||||
tool.injectServices( serviceRegistry );
|
||||
|
||||
final GenerationTargetToDatabase acmeTarget = new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
acmeProvider
|
||||
)
|
||||
);
|
||||
final GenerationTargetToDatabase jbossTarget = new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
jbossProvider
|
||||
)
|
||||
);
|
||||
|
||||
new SchemaDropperImpl( serviceRegistry ).doDrop(
|
||||
metadata,
|
||||
serviceRegistry,
|
||||
settings,
|
||||
true,
|
||||
acmeTarget,
|
||||
jbossTarget
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
acmeProvider
|
||||
)
|
||||
),
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
jbossProvider
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
new SchemaCreatorImpl( serviceRegistry ).doCreation(
|
||||
@ -104,8 +101,18 @@ public void setUp() {
|
||||
serviceRegistry,
|
||||
settings,
|
||||
true,
|
||||
acmeTarget,
|
||||
jbossTarget
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
acmeProvider
|
||||
)
|
||||
),
|
||||
new GenerationTargetToDatabase(
|
||||
new DdlTransactionIsolatorTestingImpl(
|
||||
serviceRegistry,
|
||||
jbossProvider
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
final SessionFactoryBuilder sfb = metadata.getSessionFactoryBuilder();
|
||||
|
@ -7,6 +7,7 @@
|
||||
package org.hibernate.orm.test.query.hql;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.DerbyDialect;
|
||||
|
||||
import org.hibernate.dialect.MariaDBDialect;
|
||||
@ -983,6 +984,7 @@ public void testTimestampAddDiffFunctions(SessionFactoryScope scope) {
|
||||
@SkipForDialect(dialectClass = MySQLDialect.class)
|
||||
@SkipForDialect(dialectClass = MariaDBDialect.class)
|
||||
@SkipForDialect(dialectClass = TiDBDialect.class)
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "unsupported binary operator: <timestamptz> - <date>")
|
||||
public void testDateAddDiffFunctions(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
@ -1148,20 +1150,6 @@ public void testIntervalDiffExpressions(SessionFactoryScope scope) {
|
||||
session.createQuery("select (e.theDate - e.theDate) by day from EntityOfBasics e")
|
||||
.list();
|
||||
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by year from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by month from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by day from EntityOfBasics e")
|
||||
.list();
|
||||
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by year from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by month from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by day from EntityOfBasics e")
|
||||
.list();
|
||||
|
||||
session.createQuery("select (e.theTimestamp - e.theTimestamp) by hour from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theTimestamp - e.theTimestamp) by minute from EntityOfBasics e")
|
||||
@ -1195,6 +1183,28 @@ public void testIntervalDiffExpressions(SessionFactoryScope scope) {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "unsupported binary operator: <date> - <timestamp(6)>")
|
||||
public void testIntervalDiffExpressionsDifferentTypes(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by year from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by month from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by day from EntityOfBasics e")
|
||||
.list();
|
||||
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by year from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by month from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by day from EntityOfBasics e")
|
||||
.list();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractFunction(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
@ -1401,8 +1411,6 @@ public void testExtractFunctionWithAssertions(SessionFactoryScope scope) {
|
||||
public void testFormat(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery("select format(e.theTime as 'hh:mm:ss a') from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select format(e.theDate as 'dd/MM/yy'), format(e.theDate as 'EEEE, MMMM dd, yyyy') from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select format(e.theTimestamp as 'dd/MM/yyyy ''at'' HH:mm:ss') from EntityOfBasics e")
|
||||
@ -1412,6 +1420,18 @@ public void testFormat(SessionFactoryScope scope) {
|
||||
session.createQuery("select format(theDate as 'EEEE, dd/MM/yyyy') from EntityOfBasics where id=123").getResultList().get(0),
|
||||
is("Monday, 25/03/1974")
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsFormat.class)
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "unknown signature: experimental_strftime(time, string)") // could cast the first argument to timestamp to workaround this
|
||||
public void testFormatTime(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery("select format(e.theTime as 'hh:mm:ss a') from EntityOfBasics e")
|
||||
.list();
|
||||
assertThat(
|
||||
session.createQuery("select format(theTime as '''Hello'', hh:mm:ss a') from EntityOfBasics where id=123").getResultList().get(0),
|
||||
is("Hello, 08:10:08 PM")
|
||||
|
@ -12,6 +12,8 @@
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
|
||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||
import org.hibernate.testing.orm.domain.gambit.EntityOfBasics;
|
||||
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||
@ -20,6 +22,7 @@
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -510,20 +513,6 @@ public void testIntervalDiffExpressions(SessionFactoryScope scope) {
|
||||
session.createQuery("select (e.theDate - e.theDate) by day from EntityOfBasics e")
|
||||
.list();
|
||||
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by year from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by month from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by day from EntityOfBasics e")
|
||||
.list();
|
||||
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by year from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by month from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by day from EntityOfBasics e")
|
||||
.list();
|
||||
|
||||
session.createQuery("select (e.theTimestamp - e.theTimestamp) by hour from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theTimestamp - e.theTimestamp) by minute from EntityOfBasics e")
|
||||
@ -557,6 +546,28 @@ public void testIntervalDiffExpressions(SessionFactoryScope scope) {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "unsupported binary operator: <date> - <timestamp(6)>")
|
||||
public void testIntervalDiffExpressionsDifferentTypes(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by year from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by month from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theDate - e.theTimestamp) by day from EntityOfBasics e")
|
||||
.list();
|
||||
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by year from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by month from EntityOfBasics e")
|
||||
.list();
|
||||
session.createQuery("select (e.theTimestamp - e.theDate) by day from EntityOfBasics e")
|
||||
.list();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractFunction(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
@ -881,8 +892,6 @@ public void testAggregateFunctions(SessionFactoryScope scope) {
|
||||
public void testFormat(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "select format(e.theTime as 'hh:mm:ss a') from EntityOfBasics e" )
|
||||
.list();
|
||||
session.createQuery(
|
||||
"select format(e.theDate as 'dd/MM/yy'), format(e.theDate as 'EEEE, MMMM dd, yyyy') from EntityOfBasics e" )
|
||||
.list();
|
||||
@ -897,9 +906,21 @@ public void testFormat(SessionFactoryScope scope) {
|
||||
.get( 0 ),
|
||||
is( "Monday, 25/03/1974" )
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsFormat.class)
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "unknown signature: experimental_strftime(time, string)") // could cast the first argument to timestamp to workaround this
|
||||
public void testFormatTime(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "select format(e.theTime as 'hh:mm:ss a') from EntityOfBasics e" )
|
||||
.list();
|
||||
assertThat(
|
||||
session.createQuery(
|
||||
"select format(e.theTime as '''Hello'', hh:mm:ss a') from EntityOfBasics e" )
|
||||
"select format(e.theTime as '''Hello'', hh:mm:ss a') from EntityOfBasics e" )
|
||||
.getResultList()
|
||||
.get( 0 ),
|
||||
is( "Hello, 08:10:08 PM" )
|
||||
|
@ -87,8 +87,12 @@ public void getPrimaryKey() throws Exception {
|
||||
JdbcMetadaAccessStrategy.GROUPED
|
||||
)
|
||||
.build();
|
||||
DdlTransactionIsolator ddlTransactionIsolator = null;
|
||||
ExtractionContextImpl extractionContext = null;
|
||||
try {
|
||||
TableInformation table = buildInformationExtractor( ssr ).getTable(
|
||||
ddlTransactionIsolator = buildDdlTransactionIsolator( ssr );
|
||||
extractionContext = buildContext( ssr, ddlTransactionIsolator );
|
||||
TableInformation table = buildInformationExtractor( extractionContext ).getTable(
|
||||
null,
|
||||
null,
|
||||
new Identifier( "TEST_ENTITY", false )
|
||||
@ -108,24 +112,35 @@ public void getPrimaryKey() throws Exception {
|
||||
assertTrue( pkColumnNames.contains( "b" ) );
|
||||
}
|
||||
finally {
|
||||
if ( extractionContext != null ) {
|
||||
extractionContext.cleanup();
|
||||
}
|
||||
if ( ddlTransactionIsolator != null ) {
|
||||
ddlTransactionIsolator.release();
|
||||
}
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
|
||||
private InformationExtractor buildInformationExtractor(StandardServiceRegistry ssr) throws Exception {
|
||||
ExtractionContextImpl extractionContext = buildContext( ssr );
|
||||
|
||||
private InformationExtractor buildInformationExtractor(ExtractionContextImpl extractionContext) throws Exception {
|
||||
ExtractionTool extractionTool = new HibernateSchemaManagementTool().getExtractionTool();
|
||||
|
||||
return extractionTool.createInformationExtractor( extractionContext );
|
||||
}
|
||||
|
||||
private static ExtractionContextImpl buildContext(StandardServiceRegistry ssr) throws Exception {
|
||||
private static ExtractionContextImpl buildContext(
|
||||
StandardServiceRegistry ssr,
|
||||
DdlTransactionIsolator ddlTransactionIsolator) throws Exception {
|
||||
Database database = new MetadataSources( ssr ).buildMetadata().getDatabase();
|
||||
|
||||
SqlStringGenerationContext sqlStringGenerationContext = SqlStringGenerationContextImpl.forTests( database.getJdbcEnvironment() );
|
||||
|
||||
DatabaseInformation dbInfo = buildDatabaseInformation( ssr, database, sqlStringGenerationContext );
|
||||
DatabaseInformation dbInfo = buildDatabaseInformation(
|
||||
ssr,
|
||||
database,
|
||||
sqlStringGenerationContext,
|
||||
ddlTransactionIsolator
|
||||
);
|
||||
|
||||
return new ExtractionContextImpl(
|
||||
ssr,
|
||||
@ -139,12 +154,13 @@ private static ExtractionContextImpl buildContext(StandardServiceRegistry ssr) t
|
||||
private static DatabaseInformationImpl buildDatabaseInformation(
|
||||
StandardServiceRegistry ssr,
|
||||
Database database,
|
||||
SqlStringGenerationContext sqlStringGenerationContext) throws Exception {
|
||||
SqlStringGenerationContext sqlStringGenerationContext,
|
||||
DdlTransactionIsolator ddlTransactionIsolator) throws Exception {
|
||||
return new DatabaseInformationImpl(
|
||||
ssr,
|
||||
database.getJdbcEnvironment(),
|
||||
sqlStringGenerationContext,
|
||||
buildDdlTransactionIsolator( ssr ),
|
||||
ddlTransactionIsolator,
|
||||
database.getServiceRegistry().getService( SchemaManagementTool.class )
|
||||
);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
<property name="name"/>
|
||||
<property name="company"/>
|
||||
<property name="region"/>
|
||||
<property name="region" column="p_region"/>
|
||||
|
||||
<subclass name="Employee" discriminator-value="1">
|
||||
<property name="title" column="`title`"/>
|
||||
@ -31,7 +31,7 @@
|
||||
<set name="minions" inverse="true" lazy="true" cascade="all">
|
||||
<key column="mgr_id"/>
|
||||
<one-to-many class="Employee"/>
|
||||
<filter name="region" condition="region = :userRegion"/>
|
||||
<filter name="region" condition="p_region = :userRegion"/>
|
||||
</set>
|
||||
</subclass>
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
<many-to-one name="contactOwner" class="Employee"/>
|
||||
</subclass>
|
||||
|
||||
<filter name="region" condition="region = :userRegion"/>
|
||||
<filter name="region" condition="p_region = :userRegion"/>
|
||||
|
||||
</class>
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
<property name="name"/>
|
||||
<property name="company"/>
|
||||
<property name="region"/>
|
||||
<property name="region" column="p_region"/>
|
||||
|
||||
<joined-subclass name="Employee" table="JEmployee">
|
||||
<key column="person_id"/>
|
||||
@ -39,7 +39,7 @@
|
||||
<many-to-one name="contactOwner" class="Employee"/>
|
||||
</joined-subclass>
|
||||
|
||||
<filter name="region" condition="region = :userRegion"/>
|
||||
<filter name="region" condition="p_region = :userRegion"/>
|
||||
</class>
|
||||
|
||||
<filter-def name="region">
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
<property name="name" unique="true" not-null="true"/>
|
||||
<property name="company"/>
|
||||
<property name="region"/>
|
||||
<property name="region" column="p_region"/>
|
||||
|
||||
<union-subclass name="Employee" table="UEmployee">
|
||||
<property name="title" column="emp_title"/>
|
||||
@ -28,7 +28,7 @@
|
||||
<set name="minions" inverse="true" lazy="true" cascade="all">
|
||||
<key column="mgr_id"/>
|
||||
<one-to-many class="Employee"/>
|
||||
<filter name="region" condition="region = :userRegion"/>
|
||||
<filter name="region" condition="p_region = :userRegion"/>
|
||||
</set>
|
||||
</union-subclass>
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
<many-to-one name="contactOwner" class="Employee"/>
|
||||
</union-subclass>
|
||||
|
||||
<filter name="region" condition="region = :userRegion"/>
|
||||
<filter name="region" condition="p_region = :userRegion"/>
|
||||
|
||||
</class>
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
|
||||
@ -281,11 +282,12 @@ public void testConcurrentCachedQueries(SessionFactoryScope scope) throws Except
|
||||
feature = DialectFeatureChecks.DoesReadCommittedNotCauseWritersToBlockReadersCheck.class,
|
||||
comment = "write locks block readers"
|
||||
)
|
||||
@SkipForDialect(dialectClass = CockroachDialect.class, reason = "Cockroach uses SERIALIZABLE by default and seems to fail reading a row that is exclusively locked by a different TX")
|
||||
public void testConcurrentCachedDirtyQueries(SessionFactoryScope scope) throws Exception {
|
||||
final TransactionManager transactionManager = TestingJtaPlatformImpl.INSTANCE.getTransactionManager();
|
||||
try {
|
||||
transactionManager.begin();
|
||||
final SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
|
||||
transactionManager.begin();
|
||||
Session s = sessionFactory.openSession();
|
||||
Map foo = new HashMap();
|
||||
foo.put( "name", "Foo" );
|
||||
|
@ -20,6 +20,7 @@
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.ActionQueue;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
@ -54,6 +55,11 @@ protected void applySettings(StandardServiceRegistryBuilder builder) {
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-12448")
|
||||
public void testAfterCompletionCallbackExecutedAfterTransactionTimeout() throws Exception {
|
||||
// This makes sure that hbm2ddl runs before we start a transaction for a test
|
||||
// This is important for database that only support SNAPSHOT/SERIALIZABLE isolation,
|
||||
// because a test transaction still sees the state before the DDL executed
|
||||
final SessionFactoryImplementor sessionFactory = sessionFactory();
|
||||
|
||||
// Set timeout to 5 seconds
|
||||
// Allows the reaper thread to abort our running thread for us
|
||||
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().setTransactionTimeout( 5 );
|
||||
@ -63,7 +69,7 @@ public void testAfterCompletionCallbackExecutedAfterTransactionTimeout() throws
|
||||
|
||||
Session session = null;
|
||||
try {
|
||||
session = sessionFactory().openSession();
|
||||
session = sessionFactory.openSession();
|
||||
|
||||
SimpleEntity entity = new SimpleEntity( "Hello World" );
|
||||
session.save( entity );
|
||||
|
@ -123,7 +123,7 @@ public SchemaFilter getSchemaFilter() {
|
||||
@After
|
||||
public void tearsDown() {
|
||||
try {
|
||||
connection.close();
|
||||
connectionProvider.closeConnection( connection );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
log.error( e.getMessage() );
|
||||
|
@ -30,6 +30,10 @@ public DdlTransactionIsolatorTestingImpl(ServiceRegistry serviceRegistry, JdbcCo
|
||||
super( createJdbcContext( jdbcConnectionAccess, serviceRegistry ) );
|
||||
}
|
||||
|
||||
public DdlTransactionIsolatorTestingImpl(JdbcContext jdbcContext) {
|
||||
super( jdbcContext );
|
||||
}
|
||||
|
||||
public static JdbcContext createJdbcContext(
|
||||
JdbcConnectionAccess jdbcConnectionAccess,
|
||||
ServiceRegistry serviceRegistry) {
|
||||
|
@ -40,6 +40,7 @@
|
||||
import org.hibernate.testing.orm.jpa.PersistenceUnitDescriptorAdapter;
|
||||
import org.hibernate.testing.orm.junit.DialectContext;
|
||||
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableStrategy;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.junit.After;
|
||||
|
||||
@ -147,6 +148,7 @@ protected Map getConfig() {
|
||||
config.put( AvailableSettings.ORM_XML_FILES, dds );
|
||||
}
|
||||
|
||||
config.put( PersistentTableStrategy.DROP_ID_TABLES, "true" );
|
||||
config.put( GlobalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
config.put( LocalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
if ( !Environment.getProperties().containsKey( AvailableSettings.CONNECTION_PROVIDER ) ) {
|
||||
|
@ -12,6 +12,7 @@
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.spatial.CommonSpatialFunction;
|
||||
import org.hibernate.spatial.integration.SpatialTestDataProvider;
|
||||
|
||||
@ -48,13 +49,21 @@ public boolean isSupported(CommonSpatialFunction function) {
|
||||
|
||||
protected void initH2GISExtensionsForInMemDb() {
|
||||
this.scope.inSession( session -> {
|
||||
final JdbcConnectionAccess jdbcConnectionAccess = session.getJdbcConnectionAccess();
|
||||
Connection connection = null;
|
||||
try {
|
||||
Connection cn = session.getJdbcConnectionAccess().obtainConnection();
|
||||
H2GISFunctions.load( cn );
|
||||
H2GISFunctions.load( connection = jdbcConnectionAccess.obtainConnection() );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
jdbcConnectionAccess.releaseConnection( connection );
|
||||
}
|
||||
catch (SQLException ignore) {
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
import org.hibernate.jdbc.Work;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableStrategy;
|
||||
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
|
||||
|
||||
import org.hibernate.testing.AfterClassOnce;
|
||||
@ -193,6 +194,7 @@ protected Configuration constructConfiguration(BootstrapServiceRegistry bootstra
|
||||
}
|
||||
configuration.setImplicitNamingStrategy( ImplicitNamingStrategyLegacyJpaImpl.INSTANCE );
|
||||
configuration.setProperty( Environment.DIALECT, getDialect().getClass().getName() );
|
||||
configuration.getProperties().put( PersistentTableStrategy.DROP_ID_TABLES, "true" );
|
||||
configuration.getProperties().put( GlobalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
configuration.getProperties().put( LocalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
if ( !Environment.getProperties().containsKey( Environment.CONNECTION_PROVIDER ) ) {
|
||||
|
@ -49,6 +49,7 @@
|
||||
import org.hibernate.mapping.SimpleValue;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableStrategy;
|
||||
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
|
||||
|
||||
import org.hibernate.testing.AfterClassOnce;
|
||||
@ -174,6 +175,7 @@ protected final StandardServiceRegistryBuilder constructStandardServiceRegistryB
|
||||
afterBootstrapServiceRegistryBuilt( bsr );
|
||||
|
||||
final Map<String,Object> settings = new HashMap<>();
|
||||
settings.put( PersistentTableStrategy.DROP_ID_TABLES, "true" );
|
||||
settings.put( GlobalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
settings.put( LocalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
if ( !Environment.getProperties().containsKey( Environment.CONNECTION_PROVIDER ) ) {
|
||||
|
@ -24,6 +24,7 @@
|
||||
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableStrategy;
|
||||
|
||||
import org.hibernate.testing.jdbc.SharedDriverManagerConnectionProviderImpl;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -139,6 +140,7 @@ protected Map<Object, Object> getConfig() {
|
||||
config.put( AvailableSettings.ORM_XML_FILES, dds );
|
||||
}
|
||||
|
||||
config.put( PersistentTableStrategy.DROP_ID_TABLES, "true" );
|
||||
config.put( GlobalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
config.put( LocalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
if ( !config.containsKey( Environment.CONNECTION_PROVIDER ) ) {
|
||||
|
@ -26,6 +26,7 @@
|
||||
import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableStrategy;
|
||||
import org.hibernate.tool.schema.Action;
|
||||
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
|
||||
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.ActionGrouping;
|
||||
@ -164,7 +165,7 @@ public static EntityManagerFactoryScope findEntityManagerFactoryScope(
|
||||
final Map<String, Object> integrationSettings = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
integrationSettings.put( PersistentTableStrategy.DROP_ID_TABLES, "true" );
|
||||
integrationSettings.put( GlobalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
integrationSettings.put( LocalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
if ( !integrationSettings.containsKey( Environment.CONNECTION_PROVIDER ) ) {
|
||||
|
@ -17,11 +17,16 @@
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableStrategy;
|
||||
import org.hibernate.service.spi.ServiceContributor;
|
||||
|
||||
import org.hibernate.testing.boot.ExtraJavaServicesClassLoaderService;
|
||||
import org.hibernate.testing.boot.ExtraJavaServicesClassLoaderService.JavaServiceDescriptor;
|
||||
import org.hibernate.testing.jdbc.SharedDriverManagerConnectionProviderImpl;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
|
||||
@ -186,6 +191,15 @@ public ServiceRegistryProducerImpl(Optional<ServiceRegistry> ssrAnnRef) {
|
||||
public StandardServiceRegistry produceServiceRegistry(StandardServiceRegistryBuilder ssrb) {
|
||||
// set some baseline test settings
|
||||
ssrb.applySetting( AvailableSettings.STATEMENT_INSPECTOR, org.hibernate.testing.jdbc.SQLStatementInspector.class );
|
||||
ssrb.applySetting( PersistentTableStrategy.DROP_ID_TABLES, "true" );
|
||||
ssrb.applySetting( GlobalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
ssrb.applySetting( LocalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
|
||||
if ( !ssrb.getSettings().containsKey( Environment.CONNECTION_PROVIDER ) ) {
|
||||
ssrb.applySetting(
|
||||
AvailableSettings.CONNECTION_PROVIDER,
|
||||
SharedDriverManagerConnectionProviderImpl.getInstance()
|
||||
);
|
||||
}
|
||||
|
||||
if ( ssrAnnRef.isPresent() ) {
|
||||
final ServiceRegistry serviceRegistryAnn = ssrAnnRef.get();
|
||||
|
@ -27,6 +27,7 @@
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.dialect.AbstractHANADialect;
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
@ -588,7 +589,7 @@ public static void setJdbcTimeout(Session session) {
|
||||
public static void setJdbcTimeout(Session session, long millis) {
|
||||
final Dialect dialect = session.getSessionFactory().unwrap( SessionFactoryImplementor.class ).getJdbcServices().getDialect();
|
||||
session.doWork( connection -> {
|
||||
if ( dialect instanceof PostgreSQLDialect ) {
|
||||
if ( dialect instanceof PostgreSQLDialect || dialect instanceof CockroachDialect ) {
|
||||
try (Statement st = connection.createStatement()) {
|
||||
//Prepared Statements fail for SET commands
|
||||
st.execute(String.format( "SET statement_timeout TO %d", millis / 10));
|
||||
|
322
nightly.Jenkinsfile
Normal file
322
nightly.Jenkinsfile
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
import groovy.transform.Field
|
||||
import io.jenkins.blueocean.rest.impl.pipeline.PipelineNodeGraphVisitor
|
||||
import io.jenkins.blueocean.rest.impl.pipeline.FlowNodeWrapper
|
||||
import org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper
|
||||
|
||||
/*
|
||||
* See https://github.com/hibernate/hibernate-jenkins-pipeline-helpers
|
||||
*/
|
||||
@Library('hibernate-jenkins-pipeline-helpers@1.5') _
|
||||
import org.hibernate.jenkins.pipeline.helpers.job.JobHelper
|
||||
|
||||
@Field final String DEFAULT_JDK_VERSION = '11'
|
||||
@Field final String DEFAULT_JDK_TOOL = "OpenJDK ${DEFAULT_JDK_VERSION} Latest"
|
||||
@Field final String NODE_PATTERN_BASE = 'Worker&&Containers'
|
||||
@Field List<BuildEnvironment> environments
|
||||
|
||||
this.helper = new JobHelper(this)
|
||||
|
||||
helper.runWithNotification {
|
||||
stage('Configure') {
|
||||
this.environments = [
|
||||
new BuildEnvironment( dbName: 'cockroachdb', node: 'LongDuration', longRunning: true ))
|
||||
];
|
||||
|
||||
helper.configure {
|
||||
file 'job-configuration.yaml'
|
||||
// We don't require the following, but the build helper plugin apparently does
|
||||
jdk {
|
||||
defaultTool DEFAULT_JDK_TOOL
|
||||
}
|
||||
maven {
|
||||
defaultTool 'Apache Maven 3.8'
|
||||
}
|
||||
}
|
||||
properties([
|
||||
buildDiscarder(
|
||||
logRotator(daysToKeepStr: '30', numToKeepStr: '10')
|
||||
),
|
||||
rateLimitBuilds(throttle: [count: 1, durationName: 'day', userBoost: true]),
|
||||
// If two builds are about the same branch or pull request,
|
||||
// the older one will be aborted when the newer one starts.
|
||||
disableConcurrentBuilds(abortPrevious: true),
|
||||
helper.generateNotificationProperty()
|
||||
])
|
||||
}
|
||||
|
||||
// Avoid running the pipeline on branch indexing
|
||||
if (currentBuild.getBuildCauses().toString().contains('BranchIndexingCause')) {
|
||||
print "INFO: Build skipped due to trigger being Branch Indexing"
|
||||
currentBuild.result = 'ABORTED'
|
||||
return
|
||||
}
|
||||
|
||||
stage('Build') {
|
||||
Map<String, Closure> executions = [:]
|
||||
Map<String, Map<String, String>> state = [:]
|
||||
environments.each { BuildEnvironment buildEnv ->
|
||||
// Don't build environments for newer JDKs when this is a PR
|
||||
if ( helper.scmSource.pullRequest && buildEnv.testJdkVersion ) {
|
||||
return
|
||||
}
|
||||
state[buildEnv.tag] = [:]
|
||||
executions.put(buildEnv.tag, {
|
||||
runBuildOnNode(buildEnv.node ?: NODE_PATTERN_BASE) {
|
||||
def testJavaHome
|
||||
if ( buildEnv.testJdkVersion ) {
|
||||
testJavaHome = tool(name: "OpenJDK ${buildEnv.testJdkVersion} Latest", type: 'jdk')
|
||||
}
|
||||
def javaHome = tool(name: DEFAULT_JDK_TOOL, type: 'jdk')
|
||||
// Use withEnv instead of setting env directly, as that is global!
|
||||
// See https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md
|
||||
withEnv(["JAVA_HOME=${javaHome}", "PATH+JAVA=${javaHome}/bin"]) {
|
||||
state[buildEnv.tag]['additionalOptions'] = ''
|
||||
if ( testJavaHome ) {
|
||||
state[buildEnv.tag]['additionalOptions'] = state[buildEnv.tag]['additionalOptions'] +
|
||||
" -Ptest.jdk.version=${buildEnv.testJdkVersion} -Porg.gradle.java.installations.paths=${javaHome},${testJavaHome}"
|
||||
}
|
||||
if ( buildEnv.testJdkLauncherArgs ) {
|
||||
state[buildEnv.tag]['additionalOptions'] = state[buildEnv.tag]['additionalOptions'] +
|
||||
" -Ptest.jdk.launcher.args=${buildEnv.testJdkLauncherArgs}"
|
||||
}
|
||||
state[buildEnv.tag]['containerName'] = null;
|
||||
stage('Checkout') {
|
||||
checkout scm
|
||||
}
|
||||
try {
|
||||
stage('Start database') {
|
||||
switch (buildEnv.dbName) {
|
||||
case "cockroachdb":
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('cockroachdb/cockroach:v21.1.21').pull()
|
||||
}
|
||||
sh "./docker_db.sh cockroachdb"
|
||||
state[buildEnv.tag]['containerName'] = "cockroach"
|
||||
break;
|
||||
case "mysql":
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('mysql:5.7').pull()
|
||||
}
|
||||
sh "./docker_db.sh mysql"
|
||||
state[buildEnv.tag]['containerName'] = "mysql"
|
||||
break;
|
||||
case "mysql8":
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('mysql:8.0.21').pull()
|
||||
}
|
||||
sh "./docker_db.sh mysql_8_0"
|
||||
state[buildEnv.tag]['containerName'] = "mysql"
|
||||
break;
|
||||
case "mariadb":
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('mariadb:10.7.5').pull()
|
||||
}
|
||||
sh "./docker_db.sh mariadb"
|
||||
state[buildEnv.tag]['containerName'] = "mariadb"
|
||||
break;
|
||||
case "postgresql":
|
||||
// use the postgis image to enable the PGSQL GIS (spatial) extension
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('postgis/postgis:9.5-2.5').pull()
|
||||
}
|
||||
sh "./docker_db.sh postgresql"
|
||||
state[buildEnv.tag]['containerName'] = "postgres"
|
||||
break;
|
||||
case "postgresql_14":
|
||||
// use the postgis image to enable the PGSQL GIS (spatial) extension
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('postgis/postgis:14-3.3').pull()
|
||||
}
|
||||
sh "./docker_db.sh postgresql_14"
|
||||
state[buildEnv.tag]['containerName'] = "postgres"
|
||||
break;
|
||||
case "oracle":
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('gvenzl/oracle-xe:18.4.0-full').pull()
|
||||
}
|
||||
sh "./docker_db.sh oracle_18"
|
||||
state[buildEnv.tag]['containerName'] = "oracle"
|
||||
break;
|
||||
case "db2":
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('ibmcom/db2:11.5.7.0').pull()
|
||||
}
|
||||
sh "./docker_db.sh db2"
|
||||
state[buildEnv.tag]['containerName'] = "db2"
|
||||
break;
|
||||
case "mssql":
|
||||
docker.image('mcr.microsoft.com/mssql/server@sha256:f54a84b8a802afdfa91a954e8ddfcec9973447ce8efec519adf593b54d49bedf').pull()
|
||||
sh "./docker_db.sh mssql"
|
||||
state[buildEnv.tag]['containerName'] = "mssql"
|
||||
break;
|
||||
case "sybase":
|
||||
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
||||
docker.image('nguoianphu/docker-sybase').pull()
|
||||
}
|
||||
sh "./docker_db.sh sybase"
|
||||
state[buildEnv.tag]['containerName'] = "sybase"
|
||||
break;
|
||||
case "edb":
|
||||
docker.withRegistry('https://containers.enterprisedb.com', 'hibernateci.containers.enterprisedb.com') {
|
||||
// withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'hibernateci.containers.enterprisedb.com',
|
||||
// usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
|
||||
// sh 'docker login -u "$USERNAME" -p "$PASSWORD" https://containers.enterprisedb.com'
|
||||
docker.image('containers.enterprisedb.com/edb/edb-as-lite:v11').pull()
|
||||
}
|
||||
sh "./docker_db.sh edb"
|
||||
state[buildEnv.tag]['containerName'] = "edb"
|
||||
break;
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
String cmd = "./ci/build.sh ${buildEnv.additionalOptions ?: ''} ${state[buildEnv.tag]['additionalOptions'] ?: ''}"
|
||||
withEnv(["RDBMS=${buildEnv.dbName}"]) {
|
||||
try {
|
||||
if (buildEnv.dbLockableResource == null) {
|
||||
timeout( [time: buildEnv.longRunning ? 240 : 120, unit: 'MINUTES'] ) {
|
||||
sh cmd
|
||||
}
|
||||
}
|
||||
else {
|
||||
lock(buildEnv.dbLockableResource) {
|
||||
timeout( [time: buildEnv.longRunning ? 240 : 120, unit: 'MINUTES'] ) {
|
||||
sh cmd
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
junit '**/target/test-results/test/*.xml,**/target/test-results/testKitTest/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if ( state[buildEnv.tag]['containerName'] != null ) {
|
||||
sh "docker rm -f ${state[buildEnv.tag]['containerName']}"
|
||||
}
|
||||
// Skip this for PRs
|
||||
if ( !env.CHANGE_ID && buildEnv.notificationRecipients != null ) {
|
||||
handleNotifications(currentBuild, buildEnv)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
parallel(executions)
|
||||
}
|
||||
|
||||
} // End of helper.runWithNotification
|
||||
|
||||
// Job-specific helpers
|
||||
|
||||
class BuildEnvironment {
|
||||
String testJdkVersion
|
||||
String testJdkLauncherArgs
|
||||
String dbName = 'h2'
|
||||
String node
|
||||
String dbLockableResource
|
||||
String additionalOptions
|
||||
String notificationRecipients
|
||||
boolean longRunning
|
||||
|
||||
String toString() { getTag() }
|
||||
String getTag() { "${node ? node + "_" : ''}${testJdkVersion ? 'jdk_' + testJdkVersion + '_' : '' }${dbName}" }
|
||||
}
|
||||
|
||||
void runBuildOnNode(String label, Closure body) {
|
||||
node( label ) {
|
||||
pruneDockerContainers()
|
||||
try {
|
||||
body()
|
||||
}
|
||||
finally {
|
||||
// If this is a PR, we clean the workspace at the end
|
||||
if ( env.CHANGE_BRANCH != null ) {
|
||||
cleanWs()
|
||||
}
|
||||
pruneDockerContainers()
|
||||
}
|
||||
}
|
||||
}
|
||||
void pruneDockerContainers() {
|
||||
if ( !sh( script: 'command -v docker || true', returnStdout: true ).trim().isEmpty() ) {
|
||||
sh 'docker container prune -f || true'
|
||||
sh 'docker image prune -f || true'
|
||||
sh 'docker network prune -f || true'
|
||||
sh 'docker volume prune -f || true'
|
||||
}
|
||||
}
|
||||
|
||||
void handleNotifications(currentBuild, buildEnv) {
|
||||
def currentResult = getParallelResult(currentBuild, buildEnv.tag)
|
||||
boolean success = currentResult == 'SUCCESS' || currentResult == 'UNKNOWN'
|
||||
def previousResult = currentBuild.previousBuild == null ? null : getParallelResult(currentBuild.previousBuild, buildEnv.tag)
|
||||
|
||||
// Ignore success after success
|
||||
if ( !( success && previousResult == 'SUCCESS' ) ) {
|
||||
def subject
|
||||
def body
|
||||
if ( success ) {
|
||||
if ( previousResult != 'SUCCESS' && previousResult != null ) {
|
||||
subject = "${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Fixed"
|
||||
body = """<p>${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Fixed:</p>
|
||||
<p>Check console output at <a href='${env.BUILD_URL}'>${env.BUILD_URL}</a> to view the results.</p>"""
|
||||
}
|
||||
else {
|
||||
subject = "${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Success"
|
||||
body = """<p>${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Success:</p>
|
||||
<p>Check console output at <a href='${env.BUILD_URL}'>${env.BUILD_URL}</a> to view the results.</p>"""
|
||||
}
|
||||
}
|
||||
else if (currentBuild.rawBuild.getActions(jenkins.model.InterruptedBuildAction.class).isEmpty()) {
|
||||
// If there are interrupted build actions, this means the build was cancelled, probably superseded
|
||||
// Thanks to https://issues.jenkins.io/browse/JENKINS-43339 for the "hack" to determine this
|
||||
if ( currentResult == 'FAILURE' ) {
|
||||
if ( previousResult != null && previousResult == "FAILURE" ) {
|
||||
subject = "${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Still failing"
|
||||
body = """<p>${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Still failing:</p>
|
||||
<p>Check console output at <a href='${env.BUILD_URL}'>${env.BUILD_URL}</a> to view the results.</p>"""
|
||||
}
|
||||
else {
|
||||
subject = "${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Failure"
|
||||
body = """<p>${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Failure:</p>
|
||||
<p>Check console output at <a href='${env.BUILD_URL}'>${env.BUILD_URL}</a> to view the results.</p>"""
|
||||
}
|
||||
}
|
||||
else {
|
||||
subject = "${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - ${currentResult}"
|
||||
body = """<p>${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - ${currentResult}:</p>
|
||||
<p>Check console output at <a href='${env.BUILD_URL}'>${env.BUILD_URL}</a> to view the results.</p>"""
|
||||
}
|
||||
}
|
||||
|
||||
emailext(
|
||||
subject: subject,
|
||||
body: body,
|
||||
to: buildEnv.notificationRecipients
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
String getParallelResult( RunWrapper build, String parallelBranchName ) {
|
||||
def visitor = new PipelineNodeGraphVisitor( build.rawBuild )
|
||||
def branch = visitor.pipelineNodes.find{ it.type == FlowNodeWrapper.NodeType.PARALLEL && parallelBranchName == it.displayName }
|
||||
if ( branch == null ) {
|
||||
echo "Couldn't find parallel branch name '$parallelBranchName'. Available parallel branch names:"
|
||||
visitor.pipelineNodes.findAll{ it.type == FlowNodeWrapper.NodeType.PARALLEL }.each{
|
||||
echo " - ${it.displayName}"
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return branch.status.result
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user