diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 762469a85469..6f12a415ba5c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,7 @@ jobs: - rdbms: mysql - rdbms: mariadb - rdbms: postgresql + - rdbms: gaussdb - rdbms: edb - rdbms: oracle - rdbms: db2 diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml index 79ee123c2b23..e4516b5c42e3 100644 --- a/.idea/codeStyles/codeStyleConfig.xml +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -1,5 +1,5 @@ - \ No newline at end of file diff --git a/ci/build.sh b/ci/build.sh index 26cc4a067f86..836d4f49e630 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -14,6 +14,8 @@ elif [ "$RDBMS" == "mariadb" ] || [ "$RDBMS" == "mariadb_10_4" ]; then goal="-Pdb=mariadb_ci" elif [ "$RDBMS" == "postgresql" ] || [ "$RDBMS" == "postgresql_13" ]; then goal="-Pdb=pgsql_ci" +elif [ "$RDBMS" == "gaussdb" ]; then + goal="-Pdb=gaussdb -DdbHost=localhost:5432" elif [ "$RDBMS" == "edb" ] || [ "$RDBMS" == "edb_13" ]; then goal="-Pdb=edb_ci -DdbHost=localhost:5444" elif [ "$RDBMS" == "oracle" ]; then diff --git a/ci/database-start.sh b/ci/database-start.sh index da8f3a3e78b6..a6949226d6e8 100755 --- a/ci/database-start.sh +++ b/ci/database-start.sh @@ -8,6 +8,8 @@ elif [ "$RDBMS" == 'mariadb' ]; then bash $DIR/../docker_db.sh mariadb elif [ "$RDBMS" == 'postgresql' ]; then bash $DIR/../docker_db.sh postgresql +elif [ "$RDBMS" == 'gaussdb' ]; then + bash $DIR/../docker_db.sh gaussdb elif [ "$RDBMS" == 'edb' ]; then bash $DIR/../docker_db.sh edb elif [ "$RDBMS" == 'db2' ]; then diff --git a/docker_db.sh b/docker_db.sh index e280694fb29f..efb43c0d5262 100755 --- a/docker_db.sh +++ b/docker_db.sh @@ -211,6 +211,49 @@ postgresql_17() { $CONTAINER_CLI exec postgres bash -c '/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y && apt install -y postgresql-17-pgvector && psql -U hibernate_orm_test -d hibernate_orm_test -c "create extension vector;"' } +gaussdb() { + $CONTAINER_CLI rm -f opengauss || true + + # config param + CONTAINER_NAME=opengauss + IMAGE=opengauss/opengauss:7.0.0-RC1 + PORT=5432 + DB_USER=hibernate_orm_test + DB_PASSWORD=Hibernate_orm_test@1234 + DB_NAME=hibernate_orm_test + PSQL_IMAGE=postgres:14 + + echo "🐳 start OpenGauss container..." + $CONTAINER_CLI run --name ${CONTAINER_NAME} \ + --privileged \ + -e GS_PASSWORD=${DB_PASSWORD} \ + -e GS_NODENAME=opengauss \ + -e GS_PORT=${PORT} \ + -e GS_CGROUP_DISABLE=YES \ + -p ${PORT}:5432 \ + -d ${IMAGE} + + echo "⏳ wait OpenGauss starting..." + sleep 20 + + echo " Initialize the database using the PostgreSQL client container..." + + $CONTAINER_CLI run --rm --network=host ${PSQL_IMAGE} \ + bash -c " + PGPASSWORD='${DB_PASSWORD}' psql -h localhost -p ${PORT} -U gaussdb -d postgres -c \"CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASSWORD}';\" && + PGPASSWORD='${DB_PASSWORD}' psql -h localhost -p ${PORT} -U gaussdb -d postgres -c \"CREATE DATABASE ${DB_NAME} OWNER ${DB_USER};\" && + PGPASSWORD='${DB_PASSWORD}' psql -h localhost -p ${PORT} -U gaussdb -d ${DB_NAME} -c \"CREATE SCHEMA test AUTHORIZATION ${DB_USER};\" + " + + echo "✅ Initialization completed" + echo "📌 connection information:" + echo " Host: localhost" + echo " Port: ${PORT}" + echo " Username: ${DB_USER}" + echo " Password: ${DB_PASSWORD}" + echo " Database: ${DB_NAME}" +} + edb() { edb_17 } @@ -1089,6 +1132,7 @@ if [ -z ${1} ]; then echo -e "\toracle" echo -e "\toracle_23" echo -e "\toracle_21" + echo -e "\tgauss" echo -e "\tpostgresql" echo -e "\tpostgresql_17" echo -e "\tpostgresql_16" diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractGaussDBStructJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractGaussDBStructJdbcType.java new file mode 100644 index 000000000000..e0c65ccefd6c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractGaussDBStructJdbcType.java @@ -0,0 +1,1585 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; +import java.lang.reflect.Array; +import java.sql.CallableStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAccessor; +import java.util.ArrayList; +import java.util.TimeZone; + +import org.hibernate.internal.util.CharSequenceHelper; +import org.hibernate.metamodel.mapping.EmbeddableMappingType; +import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.metamodel.mapping.MappingType; +import org.hibernate.metamodel.mapping.SelectableMapping; +import org.hibernate.metamodel.mapping.ValuedModelPart; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.spi.StringBuilderSqlAppender; +import org.hibernate.type.BasicPluralType; +import org.hibernate.type.BasicType; +import org.hibernate.type.SqlTypes; +import org.hibernate.type.descriptor.ValueExtractor; +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.IntegerJavaType; +import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; +import org.hibernate.type.descriptor.jdbc.BasicExtractor; +import org.hibernate.type.descriptor.jdbc.StructAttributeValues; +import org.hibernate.type.descriptor.jdbc.StructHelper; +import org.hibernate.type.descriptor.jdbc.StructuredJdbcType; +import org.hibernate.type.spi.TypeConfiguration; + +import static org.hibernate.type.descriptor.jdbc.StructHelper.getEmbeddedPart; +import static org.hibernate.type.descriptor.jdbc.StructHelper.instantiate; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsLocalTime; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMillis; + +/** + * Implementation for serializing/deserializing an embeddable aggregate to/from the GaussDB component format. + * For regular queries, we select the individual struct elements because the GaussDB component format encoding + * is probably not very efficient. + * + * @author liubao + * + * Notes: Original code of this class is based on AbstractPostgreSQLStructJdbcType. + */ +public abstract class AbstractGaussDBStructJdbcType implements StructuredJdbcType { + + private static final DateTimeFormatter LOCAL_DATE_TIME; + static { + LOCAL_DATE_TIME = new DateTimeFormatterBuilder() + .parseCaseInsensitive() + .append(DateTimeFormatter.ISO_LOCAL_DATE) + .appendLiteral(' ') + .append(DateTimeFormatter.ISO_LOCAL_TIME) + .optionalStart() + .appendOffset( "+HH:mm", "+00" ) + .toFormatter(); + } + + // Need a custom formatter for parsing what PostgresPlus/EDB produces + private static final DateTimeFormatter LOCAL_DATE; + static { + LOCAL_DATE = new DateTimeFormatterBuilder() + .parseCaseInsensitive() + .append(DateTimeFormatter.ISO_LOCAL_DATE) + .optionalStart() + .appendLiteral(' ') + .append(DateTimeFormatter.ISO_LOCAL_TIME) + .optionalStart() + .appendOffset( "+HH:mm", "+00" ) + .toFormatter(); + } + private final String typeName; + private final int[] orderMapping; + private final int[] inverseOrderMapping; + private final EmbeddableMappingType embeddableMappingType; + + protected AbstractGaussDBStructJdbcType( + EmbeddableMappingType embeddableMappingType, + String typeName, + int[] orderMapping) { + this.typeName = typeName; + this.embeddableMappingType = embeddableMappingType; + this.orderMapping = orderMapping; + if ( orderMapping == null ) { + this.inverseOrderMapping = null; + } + else { + final int[] inverseOrderMapping = new int[orderMapping.length]; + for ( int i = 0; i < orderMapping.length; i++ ) { + inverseOrderMapping[orderMapping[i]] = i; + } + this.inverseOrderMapping = inverseOrderMapping; + } + } + + @Override + public int getJdbcTypeCode() { + return SqlTypes.STRUCT; + } + + @Override + public String getStructTypeName() { + return typeName; + } + + @Override + public EmbeddableMappingType getEmbeddableMappingType() { + return embeddableMappingType; + } + + @Override + public JavaType getJdbcRecommendedJavaTypeMapping( + Integer precision, + Integer scale, + TypeConfiguration typeConfiguration) { + if ( embeddableMappingType == null ) { + return typeConfiguration.getJavaTypeRegistry().getDescriptor( Object[].class ); + } + else { + //noinspection unchecked + return (JavaType) embeddableMappingType.getMappedJavaType(); + } + } + + @Override + public ValueExtractor getExtractor(JavaType javaType) { + return new BasicExtractor<>( javaType, this ) { + @Override + protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException { + return getObject( rs.getObject( paramIndex ), options ); + } + + @Override + protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException { + return getObject( statement.getObject( index ), options ); + } + + @Override + protected X doExtract(CallableStatement statement, String name, WrapperOptions options) + throws SQLException { + return getObject( statement.getObject( name ), options ); + } + + private X getObject(Object object, WrapperOptions options) throws SQLException { + if ( object == null ) { + return null; + } + return ( (AbstractGaussDBStructJdbcType) getJdbcType() ).fromString( + object.toString(), + getJavaType(), + options + ); + } + }; + } + + protected X fromString(String string, JavaType javaType, WrapperOptions options) throws SQLException { + if ( string == null ) { + return null; + } + final boolean returnEmbeddable = javaType.getJavaTypeClass() != Object[].class; + final int end; + final Object[] array; + if ( embeddableMappingType == null ) { + assert !returnEmbeddable; + final ArrayList values = new ArrayList<>( 8 ); + end = deserializeStruct( string, 0, string.length() - 1, values ); + array = values.toArray(); + } + else { + array = new Object[embeddableMappingType.getJdbcValueCount() + ( embeddableMappingType.isPolymorphic() ? 1 : 0 )]; + end = deserializeStruct( string, 0, 0, array, returnEmbeddable, options ); + } + assert end == string.length(); + if ( returnEmbeddable ) { + final StructAttributeValues attributeValues = getAttributeValues( embeddableMappingType, orderMapping, array, options ); + //noinspection unchecked + return (X) instantiate( embeddableMappingType, attributeValues ); + } + else if ( inverseOrderMapping != null ) { + StructHelper.orderJdbcValues( embeddableMappingType, inverseOrderMapping, array.clone(), array ); + } + //noinspection unchecked + return (X) array; + } + + private int deserializeStruct( + String string, + int begin, + int end, + ArrayList values) { + int column = 0; + boolean inQuote = false; + boolean hasEscape = false; + assert string.charAt( begin ) == '('; + int start = begin + 1; + int element = 1; + for ( int i = start; i < string.length(); i++ ) { + final char c = string.charAt( i ); + switch ( c ) { + case '"': + if ( inQuote ) { + if ( i + 1 != end && string.charAt( i + 1 ) == '"' ) { + // Skip double quotes as that will be unescaped later + i++; + hasEscape = true; + continue; + } + if ( hasEscape ) { + values.add( unescape( string, start, i ) ); + } + else { + values.add( string.substring( start, i ) ); + } + column++; + inQuote = false; + } + else { + inQuote = true; + } + hasEscape = false; + start = i + 1; + break; + case ',': + if ( !inQuote ) { + if ( column < element ) { + if ( start == i ) { + values.add( null ); + } + else { + values.add( string.substring( start, i ) ); + } + column++; + } + start = i + 1; + element++; + } + break; + case ')': + if ( !inQuote ) { + if ( column < element ) { + if ( start == i ) { + values.add( null ); + } + else { + values.add( string.substring( start, i ) ); + } + } + return i + 1; + } + break; + } + } + + throw new IllegalArgumentException( "Struct not properly formed: " + string.subSequence( start, end ) ); + } + + private int deserializeStruct( + String string, + int begin, + int quotes, + Object[] values, + boolean returnEmbeddable, + WrapperOptions options) throws SQLException { + int column = 0; + boolean inQuote = false; + StringBuilder escapingSb = null; + assert string.charAt( begin ) == '('; + int start = begin + 1; + for ( int i = start; i < string.length(); i++ ) { + final char c = string.charAt( i ); + switch ( c ) { + case '\\': + if ( inQuote ) { + final int expectedQuoteCount = 1 << quotes; + if ( repeatsChar( string, i, expectedQuoteCount, '\\' ) ) { + if ( isDoubleQuote( string, i + expectedQuoteCount, expectedQuoteCount ) ) { + // Skip quote escaping as that will be unescaped later + if ( escapingSb == null ) { + escapingSb = new StringBuilder(); + } + escapingSb.append( string, start, i ); + escapingSb.append( '"' ); + // Move forward to the last quote + i += expectedQuoteCount + expectedQuoteCount - 1; + start = i + 1; + continue; + } + else { + assert repeatsChar( string, i + expectedQuoteCount, expectedQuoteCount, '\\' ); + // Don't create an escaping string builder for binary literals + if ( i != start || !isBinary( column ) ) { + // Skip quote escaping as that will be unescaped later + if ( escapingSb == null ) { + escapingSb = new StringBuilder(); + } + escapingSb.append( string, start, i ); + escapingSb.append( '\\' ); + start = i + expectedQuoteCount + expectedQuoteCount; + } + // Move forward to the last backslash + i += expectedQuoteCount + expectedQuoteCount - 1; + continue; + } + } + } + // Fall-through since a backslash is an escaping mechanism for a start quote within arrays + case '"': + if ( inQuote ) { + if ( isDoubleQuote( string, i, 1 << ( quotes + 1 ) ) ) { + // Skip quote escaping as that will be unescaped later + if ( escapingSb == null ) { + escapingSb = new StringBuilder(); + } + escapingSb.append( string, start, i ); + escapingSb.append( '"' ); + // Move forward to the last quote + i += ( 1 << ( quotes + 1 ) ) - 1; + start = i + 1; + continue; + } + assert isDoubleQuote( string, i, 1 << quotes ); + final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); + switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) { + case SqlTypes.DATE: + values[column] = fromRawObject( + jdbcMapping, + parseDate( + CharSequenceHelper.subSequence( + string, + start, + i + ) + ), + options + ); + break; + case SqlTypes.TIME: + case SqlTypes.TIME_WITH_TIMEZONE: + case SqlTypes.TIME_UTC: + values[column] = fromRawObject( + jdbcMapping, + parseTime( + CharSequenceHelper.subSequence( + string, + start, + i + ) + ), + options + ); + break; + case SqlTypes.TIMESTAMP: + values[column] = fromRawObject( + jdbcMapping, + parseTimestamp( + CharSequenceHelper.subSequence( + string, + start, + i + ), + jdbcMapping.getJdbcJavaType() + ), + options + ); + break; + case SqlTypes.TIMESTAMP_WITH_TIMEZONE: + case SqlTypes.TIMESTAMP_UTC: + values[column] = fromRawObject( + jdbcMapping, + parseTimestampWithTimeZone( + CharSequenceHelper.subSequence( + string, + start, + i + ), + jdbcMapping.getJdbcJavaType() + ), + options + ); + break; + case SqlTypes.BINARY: + case SqlTypes.VARBINARY: + case SqlTypes.LONGVARBINARY: + case SqlTypes.LONG32VARBINARY: + final int backslashes = 1 << ( quotes + 1 ); + assert repeatsChar( string, start, backslashes, '\\' ); + final int xCharPosition = start + backslashes; + assert string.charAt( xCharPosition ) == 'x'; + values[column] = fromString( + jdbcMapping, + string, + xCharPosition + 1, + i + ); + break; + default: + if ( escapingSb == null || escapingSb.length() == 0 ) { + values[column] = fromString( + jdbcMapping, + string, + start, + i + ); + } + else { + escapingSb.append( string, start, i ); + values[column] = fromString( + jdbcMapping, + escapingSb, + 0, + escapingSb.length() + ); + escapingSb.setLength( 0 ); + } + break; + } + column++; + inQuote = false; + // move forward the index by 2 ^ quoteLevel to point to the next char after the quote + i += 1 << quotes; + if ( string.charAt( i ) == ')' ) { + // Return the end position if this is the last element + assert column == values.length; + return i + 1; + } + // at this point, we must see a comma to indicate the next element + assert string.charAt( i ) == ','; + } + else { + // This is a start quote, so move forward the index to the last quote + final int expectedQuotes = 1 << quotes; + assert isDoubleQuote( string, i, expectedQuotes ); + i += expectedQuotes - 1; + if ( string.charAt( i + 1 ) == '(' ) { + // This could be a nested struct + final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); + if ( jdbcMapping.getJdbcType() instanceof AbstractGaussDBStructJdbcType structJdbcType ) { + final Object[] subValues = new Object[structJdbcType.embeddableMappingType.getJdbcValueCount()]; + final int subEnd = structJdbcType.deserializeStruct( + string, + i + 1, + quotes + 1, + subValues, + returnEmbeddable, + options + ); + if ( returnEmbeddable ) { + final StructAttributeValues attributeValues = structJdbcType.getAttributeValues( + structJdbcType.embeddableMappingType, + structJdbcType.orderMapping, + subValues, + options + ); + values[column] = instantiate( structJdbcType.embeddableMappingType, attributeValues ); + } + else { + if ( structJdbcType.inverseOrderMapping != null ) { + StructHelper.orderJdbcValues( + structJdbcType.embeddableMappingType, + structJdbcType.inverseOrderMapping, + subValues.clone(), + subValues + ); + } + values[column] = subValues; + } + column++; + // The subEnd points to the first character after the ')', + // so move forward the index to point to the next char after quotes + assert isDoubleQuote( string, subEnd, expectedQuotes ); + i = subEnd + expectedQuotes; + if ( string.charAt( i ) == ')' ) { + // Return the end position if this is the last element + assert column == values.length; + return i + 1; + } + // at this point, we must see a comma to indicate the next element + assert string.charAt( i ) == ','; + } + else { + inQuote = true; + } + } + else if ( string.charAt( i + 1 ) == '{' ) { + // This could be a quoted array + final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); + if ( jdbcMapping instanceof BasicPluralType pluralType ) { + final ArrayList arrayList = new ArrayList<>(); + //noinspection unchecked + final int subEnd = deserializeArray( + string, + i + 1, + quotes + 1, + arrayList, + (BasicType) pluralType.getElementType(), + returnEmbeddable, + options + ); + assert string.charAt( subEnd - 1 ) == '}'; + values[column] = pluralType.getJdbcJavaType().wrap( arrayList, options ); + column++; + // The subEnd points to the first character after the ')', + // so move forward the index to point to the next char after quotes + assert isDoubleQuote( string, subEnd, expectedQuotes ); + i = subEnd + expectedQuotes; + if ( string.charAt( i ) == ')' ) { + // Return the end position if this is the last element + assert column == values.length; + return i + 1; + } + // at this point, we must see a comma to indicate the next element + assert string.charAt( i ) == ','; + } + else { + inQuote = true; + } + } + else { + inQuote = true; + } + } + start = i + 1; + break; + case ',': + if ( !inQuote ) { + if ( start == i ) { + values[column] = null; + } + else { + final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); + if ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() == SqlTypes.BOOLEAN ) { + values[column] = fromRawObject( + jdbcMapping, + string.charAt( start ) == 't', + options + ); + } + else if ( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass().isEnum() + && jdbcMapping.getJdbcType().isInteger() ) { + values[column] = fromRawObject( + jdbcMapping, + IntegerJavaType.INSTANCE.fromEncodedString( string, start, i ), + options + ); + } + else { + values[column] = fromString( + jdbcMapping, + string, + start, + i + ); + } + } + column++; + start = i + 1; + } + break; + case ')': + if ( !inQuote ) { + if ( column < values.length ) { + if ( start == i ) { + values[column] = null; + } + else { + final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping(); + if ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() == SqlTypes.BOOLEAN ) { + values[column] = fromRawObject( + jdbcMapping, + string.charAt( start ) == 't', + options + ); + } + else if ( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass().isEnum() + && jdbcMapping.getJdbcType().isInteger() ) { + values[column] = fromRawObject( + jdbcMapping, + IntegerJavaType.INSTANCE.fromEncodedString( string, start, i ), + options + ); + } + else { + values[column] = fromString( + jdbcMapping, + string, + start, + i + ); + } + } + } + return i + 1; + } + break; + case '{': + if ( !inQuote ) { + final BasicPluralType pluralType = (BasicPluralType) getJdbcValueSelectable( column ).getJdbcMapping(); + final ArrayList arrayList = new ArrayList<>(); + //noinspection unchecked + i = deserializeArray( + string, + i, + quotes + 1, + arrayList, + (BasicType) pluralType.getElementType(), + returnEmbeddable, + options + ); + assert string.charAt( i - 1 ) == '}'; + values[column] = pluralType.getJdbcJavaType().wrap( arrayList, options ); + column++; + if ( string.charAt( i ) == ')' ) { + // Return the end position if this is the last element + assert column == values.length; + return i + 1; + } + // at this point, we must see a comma to indicate the next element + assert string.charAt( i ) == ','; + start = i + 1; + } + break; + } + } + + throw new IllegalArgumentException( "Struct not properly formed: " + string.substring( start ) ); + } + + private boolean isBinary(int column) { + return isBinary( getJdbcValueSelectable( column ).getJdbcMapping() ); + } + + private static boolean isBinary(JdbcMapping jdbcMapping) { + switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) { + case SqlTypes.BINARY: + case SqlTypes.VARBINARY: + case SqlTypes.LONGVARBINARY: + case SqlTypes.LONG32VARBINARY: + return true; + } + return false; + } + + private int deserializeArray( + String string, + int begin, + int quotes, + ArrayList values, + BasicType elementType, + boolean returnEmbeddable, + WrapperOptions options) throws SQLException { + boolean inQuote = false; + StringBuilder escapingSb = null; + assert string.charAt( begin ) == '{'; + int start = begin + 1; + for ( int i = start; i < string.length(); i++ ) { + final char c = string.charAt( i ); + switch ( c ) { + case '\\': + if ( inQuote ) { + final int expectedQuoteCount = 1 << quotes; + if ( repeatsChar( string, i, expectedQuoteCount, '\\' ) ) { + if ( isDoubleQuote( string, i + expectedQuoteCount, expectedQuoteCount ) ) { + // Skip quote escaping as that will be unescaped later + if ( escapingSb == null ) { + escapingSb = new StringBuilder(); + } + escapingSb.append( string, start, i ); + escapingSb.append( '"' ); + // Move forward to the last quote + i += expectedQuoteCount + expectedQuoteCount - 1; + start = i + 1; + continue; + } + else { + assert repeatsChar( string, i + expectedQuoteCount, expectedQuoteCount, '\\' ); + // Don't create an escaping string builder for binary literals + if ( i != start || !isBinary( elementType ) ) { + // Skip quote escaping as that will be unescaped later + if ( escapingSb == null ) { + escapingSb = new StringBuilder(); + } + escapingSb.append( string, start, i ); + escapingSb.append( '\\' ); + start = i + expectedQuoteCount + expectedQuoteCount; + } + // Move forward to the last backslash + i += expectedQuoteCount + expectedQuoteCount - 1; + continue; + } + } + } + // Fall-through since a backslash is an escaping mechanism for a start quote within arrays + case '"': + if ( inQuote ) { + if ( isDoubleQuote( string, i, 1 << ( quotes + 1 ) ) ) { + // Skip quote escaping as that will be unescaped later + if ( escapingSb == null ) { + escapingSb = new StringBuilder(); + } + escapingSb.append( string, start, i ); + escapingSb.append( '"' ); + // Move forward to the last quote + i += ( 1 << ( quotes + 1 ) ) - 1; + start = i + 1; + continue; + } + assert isDoubleQuote( string, i, 1 << quotes ); + switch ( elementType.getJdbcType().getDefaultSqlTypeCode() ) { + case SqlTypes.DATE: + values.add( + fromRawObject( + elementType, + parseDate( + CharSequenceHelper.subSequence( + string, + start, + i + ) + ), + options + ) + ); + break; + case SqlTypes.TIME: + case SqlTypes.TIME_WITH_TIMEZONE: + case SqlTypes.TIME_UTC: + values.add( + fromRawObject( + elementType, + parseTime( + CharSequenceHelper.subSequence( + string, + start, + i + ) + ), + options + ) + ); + break; + case SqlTypes.TIMESTAMP: + values.add( + fromRawObject( + elementType, + parseTimestamp( + CharSequenceHelper.subSequence( + string, + start, + i + ), + elementType.getJdbcJavaType() + ), + options + ) + ); + break; + case SqlTypes.TIMESTAMP_WITH_TIMEZONE: + case SqlTypes.TIMESTAMP_UTC: + values.add( + fromRawObject( + elementType, + parseTimestampWithTimeZone( + CharSequenceHelper.subSequence( + string, + start, + i + ), + elementType.getJdbcJavaType() + ), + options + ) + ); + break; + case SqlTypes.BINARY: + case SqlTypes.VARBINARY: + case SqlTypes.LONGVARBINARY: + case SqlTypes.LONG32VARBINARY: + final int backslashes = 1 << ( quotes + 1 ); + assert repeatsChar( string, start, backslashes, '\\' ); + final int xCharPosition = start + backslashes; + assert string.charAt( xCharPosition ) == 'x'; + values.add( + fromString( + elementType, + string, + xCharPosition + 1, + i + ) + ); + break; + default: + if ( escapingSb == null || escapingSb.length() == 0 ) { + values.add( + fromString( + elementType, + string, + start, + i + ) + ); + } + else { + escapingSb.append( string, start, i ); + values.add( + fromString( + elementType, + escapingSb, + 0, + escapingSb.length() + ) + ); + escapingSb.setLength( 0 ); + } + break; + } + inQuote = false; + // move forward the index by 2 ^ quotes to point to the next char after the quote + i += 1 << quotes; + if ( string.charAt( i ) == '}' ) { + // Return the end position if this is the last element + return i + 1; + } + // at this point, we must see a comma to indicate the next element + assert string.charAt( i ) == ','; + } + else { + // This is a start quote, so move forward the index to the last quote + final int expectedQuotes = 1 << quotes; + assert isDoubleQuote( string, i, expectedQuotes ); + i += expectedQuotes - 1; + if ( string.charAt( i + 1 ) == '(' ) { + // This could be a nested struct + if ( elementType.getJdbcType() instanceof AbstractGaussDBStructJdbcType structJdbcType ) { + final Object[] subValues = new Object[structJdbcType.embeddableMappingType.getJdbcValueCount()]; + final int subEnd = structJdbcType.deserializeStruct( + string, + i + 1, + quotes + 1, + subValues, + returnEmbeddable, + options + ); + if ( returnEmbeddable ) { + final StructAttributeValues attributeValues = structJdbcType.getAttributeValues( + structJdbcType.embeddableMappingType, + structJdbcType.orderMapping, + subValues, + options + ); + values.add( instantiate( structJdbcType.embeddableMappingType, attributeValues ) ); + } + else { + if ( structJdbcType.inverseOrderMapping != null ) { + StructHelper.orderJdbcValues( + structJdbcType.embeddableMappingType, + structJdbcType.inverseOrderMapping, + subValues.clone(), + subValues + ); + } + values.add( subValues ); + } + // The subEnd points to the first character after the '}', + // so move forward the index to point to the next char after quotes + assert isDoubleQuote( string, subEnd, expectedQuotes ); + i = subEnd + expectedQuotes; + if ( string.charAt( i ) == '}' ) { + // Return the end position if this is the last element + return i + 1; + } + // at this point, we must see a comma to indicate the next element + assert string.charAt( i ) == ','; + } + else { + inQuote = true; + } + } + else { + inQuote = true; + } + } + start = i + 1; + switch ( elementType.getJdbcType().getDefaultSqlTypeCode() ) { + case SqlTypes.BINARY: + case SqlTypes.VARBINARY: + case SqlTypes.LONGVARBINARY: + case SqlTypes.LONG32VARBINARY: + // Skip past the backslashes in the binary literal, this will be handled later + final int backslashes = 1 << ( quotes + 1 ); + assert repeatsChar( string, start, backslashes, '\\' ); + i += backslashes; + break; + } + break; + case ',': + if ( !inQuote ) { + if ( start == i ) { + values.add( null ); + } + else { + if ( elementType.getJdbcType().getDefaultSqlTypeCode() == SqlTypes.BOOLEAN ) { + values.add( + fromRawObject( + elementType, + string.charAt( start ) == 't', + options + ) + ); + } + else if ( elementType.getJavaTypeDescriptor().getJavaTypeClass().isEnum() + && elementType.getJdbcType().isInteger() ) { + values.add( + fromRawObject( + elementType, + IntegerJavaType.INSTANCE.fromEncodedString( string, start, i ), + options + ) + ); + } + else { + values.add( + fromString( + elementType, + string, + start, + i + ) + ); + } + } + start = i + 1; + } + break; + case '}': + if ( !inQuote ) { + if ( start == i ) { + values.add( null ); + } + else { + if ( elementType.getJdbcType().getDefaultSqlTypeCode() == SqlTypes.BOOLEAN ) { + values.add( + fromRawObject( + elementType, + string.charAt( start ) == 't', + options + ) + ); + } + else if ( elementType.getJavaTypeDescriptor().getJavaTypeClass().isEnum() + && elementType.getJdbcType().isInteger() ) { + values.add( + fromRawObject( + elementType, + IntegerJavaType.INSTANCE.fromEncodedString( string, start, i ), + options + ) + ); + } + else { + values.add( + fromString( + elementType, + string, + start, + i + ) + ); + } + } + return i + 1; + } + break; + } + } + + throw new IllegalArgumentException( "Array not properly formed: " + string.substring( start ) ); + } + + private SelectableMapping getJdbcValueSelectable(int jdbcValueSelectableIndex) { + if ( orderMapping != null ) { + final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings(); + final int size = numberOfAttributeMappings + ( embeddableMappingType.isPolymorphic() ? 1 : 0 ); + int count = 0; + for ( int i = 0; i < size; i++ ) { + final ValuedModelPart modelPart = getEmbeddedPart( embeddableMappingType, orderMapping[i] ); + if ( modelPart.getMappedType() instanceof EmbeddableMappingType embeddableMappingType ) { + final SelectableMapping aggregateMapping = embeddableMappingType.getAggregateMapping(); + if ( aggregateMapping == null ) { + final SelectableMapping subSelectable = embeddableMappingType.getJdbcValueSelectable( jdbcValueSelectableIndex - count ); + if ( subSelectable != null ) { + return subSelectable; + } + count += embeddableMappingType.getJdbcValueCount(); + } + else { + if ( count == jdbcValueSelectableIndex ) { + return aggregateMapping; + } + count++; + } + } + else { + if ( count == jdbcValueSelectableIndex ) { + return (SelectableMapping) modelPart; + } + count += modelPart.getJdbcTypeCount(); + } + } + return null; + } + return embeddableMappingType.getJdbcValueSelectable( jdbcValueSelectableIndex ); + } + + private static boolean repeatsChar(String string, int start, int times, char expectedChar) { + final int end = start + times; + if ( end < string.length() ) { + for ( ; start < end; start++ ) { + if ( string.charAt( start ) != expectedChar ) { + return false; + } + } + return true; + } + return false; + } + + private static boolean isDoubleQuote(String string, int start, int escapes) { + if ( escapes == 1 ) { + return string.charAt( start ) == '"'; + } + assert ( escapes & 1 ) == 0 : "Only an even number of escapes allowed"; + final int end = start + escapes; + if ( end < string.length() ) { + for ( ; start < end; start += 2 ) { + final char c1 = string.charAt( start ); + final char c2 = string.charAt( start + 1 ); + switch ( c1 ) { + case '\\': + // After a backslash, another backslash or a double quote may follow + if ( c2 != '\\' && c2 != '"' ) { + return false; + } + break; + case '"': + // After a double quote, only another double quote may follow + if ( c2 != '"' ) { + return false; + } + break; + default: + return false; + } + } + return string.charAt( end - 1 ) == '"'; + } + return false; + } + + private Object fromString( + int selectableIndex, + String string, + int start, + int end) { + return fromString( + getJdbcValueSelectable( selectableIndex ).getJdbcMapping(), + string, + start, + end + ); + } + + private static Object fromString(JdbcMapping jdbcMapping, CharSequence charSequence, int start, int end) { + return jdbcMapping.getJdbcJavaType().fromEncodedString( + charSequence, + start, + end + ); + } + + private static Object fromRawObject(JdbcMapping jdbcMapping, Object raw, WrapperOptions options) { + return jdbcMapping.getJdbcJavaType().wrap( + raw, + options + ); + } + + private Object parseDate(CharSequence subSequence) { + return LOCAL_DATE.parse( subSequence, LocalDate::from ); + } + + private Object parseTime(CharSequence subSequence) { + return DateTimeFormatter.ISO_LOCAL_TIME.parse( subSequence, LocalTime::from ); + } + + private Object parseTimestamp(CharSequence subSequence, JavaType jdbcJavaType) { + final TemporalAccessor temporalAccessor = LOCAL_DATE_TIME.parse( subSequence ); + final LocalDateTime localDateTime = LocalDateTime.from( temporalAccessor ); + final Timestamp timestamp = Timestamp.valueOf( localDateTime ); + timestamp.setNanos( temporalAccessor.get( ChronoField.NANO_OF_SECOND ) ); + return timestamp; + } + + private Object parseTimestampWithTimeZone(CharSequence subSequence, JavaType jdbcJavaType) { + final TemporalAccessor temporalAccessor = LOCAL_DATE_TIME.parse( subSequence ); + if ( temporalAccessor.isSupported( ChronoField.OFFSET_SECONDS ) ) { + if ( jdbcJavaType.getJavaTypeClass() == Instant.class ) { + return Instant.from( temporalAccessor ); + } + else { + return OffsetDateTime.from( temporalAccessor ); + } + } + return LocalDateTime.from( temporalAccessor ); + } + + private static String unescape(CharSequence string, int start, int end) { + StringBuilder sb = new StringBuilder( end - start ); + for ( int i = start; i < end; i++ ) { + final char c = string.charAt( i ); + if ( c == '\\' || c == '"' ) { + i++; + sb.append( string.charAt( i ) ); + continue; + } + sb.append( c ); + } + return sb.toString(); + } + + @Override + public Object createJdbcValue(Object domainValue, WrapperOptions options) throws SQLException { + assert embeddableMappingType != null; + final StringBuilder sb = new StringBuilder(); + serializeStructTo( new PostgreSQLAppender( sb ), domainValue, options ); + return sb.toString(); + } + + @Override + public Object[] extractJdbcValues(Object rawJdbcValue, WrapperOptions options) throws SQLException { + assert embeddableMappingType != null; + final Object[] array = new Object[embeddableMappingType.getJdbcValueCount()]; + deserializeStruct( getRawStructFromJdbcValue( rawJdbcValue ), 0, 0, array, true, options ); + if ( inverseOrderMapping != null ) { + StructHelper.orderJdbcValues( embeddableMappingType, inverseOrderMapping, array.clone(), array ); + } + return array; + } + + protected String getRawStructFromJdbcValue(Object rawJdbcValue) { + return rawJdbcValue.toString(); + } + + protected String toString(X value, JavaType javaType, WrapperOptions options) throws SQLException { + if ( value == null ) { + return null; + } + final StringBuilder sb = new StringBuilder(); + serializeStructTo( new PostgreSQLAppender( sb ), value, options ); + return sb.toString(); + } + + private void serializeStructTo(PostgreSQLAppender appender, Object value, WrapperOptions options) throws SQLException { + serializeDomainValueTo( appender, options, value, '(' ); + appender.append( ')' ); + } + + private void serializeDomainValueTo( + PostgreSQLAppender appender, + WrapperOptions options, + Object domainValue, + char separator) throws SQLException { + serializeJdbcValuesTo( + appender, + options, + StructHelper.getJdbcValues( embeddableMappingType, orderMapping, domainValue, options ), + separator + ); + } + + private void serializeJdbcValuesTo( + PostgreSQLAppender appender, + WrapperOptions options, + Object[] jdbcValues, + char separator) throws SQLException { + for ( int i = 0; i < jdbcValues.length; i++ ) { + appender.append( separator ); + separator = ','; + final Object jdbcValue = jdbcValues[i]; + if ( jdbcValue == null ) { + continue; + } + final SelectableMapping selectableMapping = orderMapping == null ? + embeddableMappingType.getJdbcValueSelectable( i ) : + embeddableMappingType.getJdbcValueSelectable( orderMapping[i] ); + final JdbcMapping jdbcMapping = selectableMapping.getJdbcMapping(); + if ( jdbcMapping.getJdbcType() instanceof AbstractGaussDBStructJdbcType structJdbcType ) { + appender.quoteStart(); + structJdbcType.serializeJdbcValuesTo( + appender, + options, + (Object[]) jdbcValue, + '(' + ); + appender.append( ')' ); + appender.quoteEnd(); + } + else { + serializeConvertedBasicTo( appender, options, jdbcMapping, jdbcValue ); + } + } + } + + private void serializeConvertedBasicTo( + PostgreSQLAppender appender, + WrapperOptions options, + JdbcMapping jdbcMapping, + Object subValue) throws SQLException { + //noinspection unchecked + final JavaType jdbcJavaType = (JavaType) jdbcMapping.getJdbcJavaType(); + switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) { + case SqlTypes.TINYINT: + case SqlTypes.SMALLINT: + case SqlTypes.INTEGER: + if ( subValue instanceof Boolean booleanValue ) { + // BooleanJavaType has this as an implicit conversion + appender.append( booleanValue ? '1' : '0' ); + break; + } + if ( subValue instanceof Enum enumValue ) { + appender.appendSql( enumValue.ordinal() ); + break; + } + case SqlTypes.BOOLEAN: + case SqlTypes.BIT: + case SqlTypes.BIGINT: + case SqlTypes.FLOAT: + case SqlTypes.REAL: + case SqlTypes.DOUBLE: + case SqlTypes.DECIMAL: + case SqlTypes.NUMERIC: + case SqlTypes.DURATION: + appender.append( subValue.toString() ); + break; + case SqlTypes.CHAR: + case SqlTypes.NCHAR: + case SqlTypes.VARCHAR: + case SqlTypes.NVARCHAR: + if ( subValue instanceof Boolean booleanValue ) { + // BooleanJavaType has this as an implicit conversion + appender.append( booleanValue ? 'Y' : 'N' ); + break; + } + case SqlTypes.LONGVARCHAR: + case SqlTypes.LONGNVARCHAR: + case SqlTypes.LONG32VARCHAR: + case SqlTypes.LONG32NVARCHAR: + case SqlTypes.ENUM: + case SqlTypes.NAMED_ENUM: + appender.quoteStart(); + appender.append( (String) subValue ); + appender.quoteEnd(); + break; + case SqlTypes.DATE: + case SqlTypes.TIME: + case SqlTypes.TIME_WITH_TIMEZONE: + case SqlTypes.TIME_UTC: + case SqlTypes.TIMESTAMP: + case SqlTypes.TIMESTAMP_WITH_TIMEZONE: + case SqlTypes.TIMESTAMP_UTC: + appendTemporal( appender, jdbcMapping, subValue, options ); + break; + case SqlTypes.BINARY: + case SqlTypes.VARBINARY: + case SqlTypes.LONGVARBINARY: + case SqlTypes.LONG32VARBINARY: + final byte[] bytes = jdbcJavaType.unwrap( + subValue, + byte[].class, + options + ); + appender.ensureCanFit( appender.quote + 1 + ( bytes.length << 1 ) ); + appender.append( '\\' ); + appender.append( '\\' ); + appender.append( 'x' ); + PrimitiveByteArrayJavaType.INSTANCE.appendString( + appender, + bytes + ); + break; + case SqlTypes.UUID: + appender.append( subValue.toString() ); + break; + case SqlTypes.ARRAY: + if ( subValue != null ) { + final int length = Array.getLength( subValue ); + if ( length == 0 ) { + appender.append( "{}" ); + } + else { + //noinspection unchecked + final BasicType elementType = ((BasicPluralType) jdbcMapping).getElementType(); + appender.quoteStart(); + appender.append( '{' ); + Object arrayElement = Array.get( subValue, 0 ); + if ( arrayElement == null ) { + appender.appendNull(); + } + else { + serializeConvertedBasicTo( appender, options, elementType, arrayElement ); + } + for ( int i = 1; i < length; i++ ) { + arrayElement = Array.get( subValue, i ); + appender.append( ',' ); + if ( arrayElement == null ) { + appender.appendNull(); + } + else { + serializeConvertedBasicTo( appender, options, elementType, arrayElement ); + } + } + + appender.append( '}' ); + appender.quoteEnd(); + } + } + break; + case SqlTypes.STRUCT: + if ( subValue != null ) { + final AbstractGaussDBStructJdbcType structJdbcType = (AbstractGaussDBStructJdbcType) jdbcMapping.getJdbcType(); + appender.quoteStart(); + structJdbcType.serializeJdbcValuesTo( appender, options, (Object[]) subValue, '(' ); + appender.append( ')' ); + appender.quoteEnd(); + } + break; + default: + throw new UnsupportedOperationException( "Unsupported JdbcType nested in struct: " + jdbcMapping.getJdbcType() ); + } + } + + private StructAttributeValues getAttributeValues( + EmbeddableMappingType embeddableMappingType, + int[] orderMapping, + Object[] rawJdbcValues, + WrapperOptions options) throws SQLException { + final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings(); + final int size = numberOfAttributeMappings + ( embeddableMappingType.isPolymorphic() ? 1 : 0 ); + final StructAttributeValues attributeValues = new StructAttributeValues( + numberOfAttributeMappings, + orderMapping != null ? + null : + rawJdbcValues + ); + int jdbcIndex = 0; + for ( int i = 0; i < size; i++ ) { + final int attributeIndex; + if ( orderMapping == null ) { + attributeIndex = i; + } + else { + attributeIndex = orderMapping[i]; + } + jdbcIndex += injectAttributeValue( + getEmbeddedPart( embeddableMappingType, attributeIndex ), + attributeValues, + attributeIndex, + rawJdbcValues, + jdbcIndex, + options + ); + } + return attributeValues; + } + + private int injectAttributeValue( + ValuedModelPart modelPart, + StructAttributeValues attributeValues, + int attributeIndex, + Object[] rawJdbcValues, + int jdbcIndex, + WrapperOptions options) throws SQLException { + final MappingType mappedType = modelPart.getMappedType(); + final int jdbcValueCount; + final Object rawJdbcValue = rawJdbcValues[jdbcIndex]; + if ( mappedType instanceof EmbeddableMappingType embeddableMappingType ) { + if ( embeddableMappingType.getAggregateMapping() != null ) { + jdbcValueCount = 1; + attributeValues.setAttributeValue( attributeIndex, rawJdbcValue ); + } + else { + jdbcValueCount = embeddableMappingType.getJdbcValueCount(); + final Object[] subJdbcValues = new Object[jdbcValueCount]; + System.arraycopy( rawJdbcValues, jdbcIndex, subJdbcValues, 0, subJdbcValues.length ); + final StructAttributeValues subValues = getAttributeValues( + embeddableMappingType, + null, + subJdbcValues, + options + ); + attributeValues.setAttributeValue( attributeIndex, instantiate( embeddableMappingType, subValues ) ); + } + } + else { + assert modelPart.getJdbcTypeCount() == 1; + jdbcValueCount = 1; + final JdbcMapping jdbcMapping = modelPart.getSingleJdbcMapping(); + final Object jdbcValue = jdbcMapping.getJdbcJavaType().wrap( + rawJdbcValue, + options + ); + attributeValues.setAttributeValue( attributeIndex, jdbcMapping.convertToDomainValue( jdbcValue ) ); + } + return jdbcValueCount; + } + + private void appendTemporal(SqlAppender appender, JdbcMapping jdbcMapping, Object value, WrapperOptions options) { + final TimeZone jdbcTimeZone = getJdbcTimeZone( options ); + //noinspection unchecked + final JavaType javaType = (JavaType) jdbcMapping.getJdbcJavaType(); + appender.append( '"' ); + switch ( jdbcMapping.getJdbcType().getJdbcTypeCode() ) { + case SqlTypes.DATE: + if ( value instanceof java.util.Date date ) { + appendAsDate( appender, date ); + } + else if ( value instanceof java.util.Calendar calendar ) { + appendAsDate( appender, calendar ); + } + else if ( value instanceof TemporalAccessor temporalAccessor ) { + appendAsDate( appender, temporalAccessor ); + } + else { + appendAsDate( + appender, + javaType.unwrap( value, java.util.Date.class, options ) + ); + } + break; + case SqlTypes.TIME: + case SqlTypes.TIME_WITH_TIMEZONE: + case SqlTypes.TIME_UTC: + if ( value instanceof java.util.Date date ) { + appendAsTime( appender, date, jdbcTimeZone ); + } + else if ( value instanceof java.util.Calendar calendar ) { + appendAsTime( appender, calendar, jdbcTimeZone ); + } + else if ( value instanceof TemporalAccessor temporalAccessor ) { + if ( temporalAccessor.isSupported( ChronoField.OFFSET_SECONDS ) ) { + appendAsTime( appender, temporalAccessor, true, jdbcTimeZone ); + } + else { + appendAsLocalTime( appender, temporalAccessor ); + } + } + else { + appendAsTime( + appender, + javaType.unwrap( value, java.sql.Time.class, options ), + jdbcTimeZone + ); + } + break; + case SqlTypes.TIMESTAMP: + case SqlTypes.TIMESTAMP_WITH_TIMEZONE: + case SqlTypes.TIMESTAMP_UTC: + if ( value instanceof java.util.Date date ) { + appendAsTimestampWithMicros( appender, date, jdbcTimeZone ); + } + else if ( value instanceof java.util.Calendar calendar ) { + appendAsTimestampWithMillis( appender, calendar, jdbcTimeZone ); + } + else if ( value instanceof TemporalAccessor temporalAccessor ) { + appendAsTimestampWithMicros( appender, temporalAccessor, temporalAccessor.isSupported( ChronoField.OFFSET_SECONDS ), jdbcTimeZone ); + } + else { + appendAsTimestampWithMicros( + appender, + javaType.unwrap( value, java.util.Date.class, options ), + jdbcTimeZone + ); + } + break; + default: + throw new IllegalArgumentException(); + } + + appender.append( '"' ); + } + private static TimeZone getJdbcTimeZone(WrapperOptions options) { + return options == null || options.getJdbcTimeZone() == null + ? TimeZone.getDefault() + : options.getJdbcTimeZone(); + } + + protected Object getBindValue(X value, WrapperOptions options) throws SQLException { + return StructHelper.getJdbcValues( embeddableMappingType, orderMapping, value, options ); + } + + private static class PostgreSQLAppender extends StringBuilderSqlAppender { + + private int quote = 1; + + public PostgreSQLAppender(StringBuilder sb) { + super( sb ); + } + + public void quoteStart() { + append( '"' ); + quote = quote << 1; + } + + public void quoteEnd() { + quote = quote >> 1; + append( '"' ); + } + + public void appendNull() { + sb.append( "NULL" ); + } + + @Override + public PostgreSQLAppender append(char fragment) { + if ( quote != 1 ) { + appendWithQuote( fragment ); + } + else { + sb.append( fragment ); + } + return this; + } + + @Override + public PostgreSQLAppender append(CharSequence csq) { + return append( csq, 0, csq.length() ); + } + + @Override + public PostgreSQLAppender append(CharSequence csq, int start, int end) { + if ( quote != 1 ) { + int len = end - start; + sb.ensureCapacity( sb.length() + len ); + for ( int i = start; i < end; i++ ) { + appendWithQuote( csq.charAt( i ) ); + } + } + else { + sb.append( csq, start, end ); + } + return this; + } + + private void appendWithQuote(char fragment) { + if ( fragment == '"' || fragment == '\\' ) { + sb.ensureCapacity( sb.length() + quote ); + for ( int i = 1; i < quote; i++ ) { + sb.append( '\\' ); + } + } + sb.append( fragment ); + } + + public void ensureCanFit(int lengthIncrease) { + sb.ensureCapacity( sb.length() + lengthIncrease ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Database.java b/hibernate-core/src/main/java/org/hibernate/dialect/Database.java index cb24d2ea2839..3f727ac4c82f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Database.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Database.java @@ -79,6 +79,21 @@ public String getUrlPrefix() { } }, + GAUSSDB { + @Override + public Dialect createDialect(DialectResolutionInfo info) { + return new GaussDBDialect(info); + } + @Override + public boolean productNameMatches(String databaseName) { + return "GaussDB".equals( databaseName ); + } + @Override + public String getDriverClassName(String jdbcUrl) { + return "com.huawei.gaussdb.jdbc.Driver"; + } + }, + H2 { @Override public Dialect createDialect(DialectResolutionInfo info) { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBArrayJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBArrayJdbcType.java new file mode 100644 index 000000000000..c6f531ec3f7a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBArrayJdbcType.java @@ -0,0 +1,101 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Types; + +import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.type.descriptor.ValueBinder; +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.BasicPluralJavaType; +import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; +import org.hibernate.type.descriptor.jdbc.ArrayJdbcType; +import org.hibernate.type.descriptor.jdbc.BasicBinder; +import org.hibernate.type.descriptor.jdbc.JdbcType; + +/** + * Descriptor for {@link Types#ARRAY ARRAY} handling. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLArrayJdbcType. + */ +public class GaussDBArrayJdbcType extends ArrayJdbcType { + + public GaussDBArrayJdbcType(JdbcType elementJdbcType) { + super( elementJdbcType ); + } + + @Override + public ValueBinder getBinder(final JavaType javaTypeDescriptor) { + @SuppressWarnings("unchecked") + final BasicPluralJavaType pluralJavaType = (BasicPluralJavaType) javaTypeDescriptor; + final ValueBinder elementBinder = getElementJdbcType().getBinder( pluralJavaType.getElementJavaType() ); + return new BasicBinder<>( javaTypeDescriptor, this ) { + + @Override + protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException { + st.setArray( index, getArray( value, options ) ); + } + + @Override + protected void doBind(CallableStatement st, X value, String name, WrapperOptions options) + throws SQLException { + final java.sql.Array arr = getArray( value, options ); + try { + st.setObject( name, arr, java.sql.Types.ARRAY ); + } + catch (SQLException ex) { + throw new HibernateException( "JDBC driver does not support named parameters for setArray. Use positional.", ex ); + } + } + + @Override + public Object getBindValue(X value, WrapperOptions options) throws SQLException { + return ( (GaussDBArrayJdbcType) getJdbcType() ).getArray( this, elementBinder, value, options ); + } + + private java.sql.Array getArray(X value, WrapperOptions options) throws SQLException { + final GaussDBArrayJdbcType arrayJdbcType = (GaussDBArrayJdbcType) getJdbcType(); + final Object[] objects; + + final JdbcType elementJdbcType = arrayJdbcType.getElementJdbcType(); + if ( elementJdbcType instanceof AggregateJdbcType ) { + // The GaussDB JDBC driver does not support arrays of structs, which contain byte[] + final AggregateJdbcType aggregateJdbcType = (AggregateJdbcType) elementJdbcType; + final Object[] domainObjects = getJavaType().unwrap( + value, + Object[].class, + options + ); + objects = new Object[domainObjects.length]; + for ( int i = 0; i < domainObjects.length; i++ ) { + if ( domainObjects[i] != null ) { + objects[i] = aggregateJdbcType.createJdbcValue( domainObjects[i], options ); + } + } + } + else { + objects = arrayJdbcType.getArray( this, elementBinder, value, options ); + } + + final SharedSessionContractImplementor session = options.getSession(); + final String typeName = arrayJdbcType.getElementTypeName( getJavaType(), session ); + return session.getJdbcCoordinator().getLogicalConnection().getPhysicalConnection() + .createArrayOf( typeName, objects ); + } + }; + } + + @Override + public String toString() { + return "GaussDBArrayTypeDescriptor(" + getElementJdbcType().toString() + ")"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBArrayJdbcTypeConstructor.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBArrayJdbcTypeConstructor.java new file mode 100644 index 000000000000..b37553dc3657 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBArrayJdbcTypeConstructor.java @@ -0,0 +1,48 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import java.sql.Types; + +import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; +import org.hibernate.type.BasicType; +import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * Factory for {@link GaussDBArrayJdbcType}. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLArrayJdbcTypeConstructor. + */ +public class GaussDBArrayJdbcTypeConstructor implements JdbcTypeConstructor { + + public static final GaussDBArrayJdbcTypeConstructor INSTANCE = new GaussDBArrayJdbcTypeConstructor(); + + @Override + public JdbcType resolveType( + TypeConfiguration typeConfiguration, + Dialect dialect, + BasicType elementType, + ColumnTypeInformation columnTypeInformation) { + return resolveType( typeConfiguration, dialect, elementType.getJdbcType(), columnTypeInformation ); + } + + @Override + public JdbcType resolveType( + TypeConfiguration typeConfiguration, + Dialect dialect, + JdbcType elementType, + ColumnTypeInformation columnTypeInformation) { + return new GaussDBArrayJdbcType( elementType ); + } + + @Override + public int getDefaultSqlTypeCode() { + return Types.ARRAY; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingInetJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingInetJdbcType.java new file mode 100644 index 000000000000..f76ecd18bfc9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingInetJdbcType.java @@ -0,0 +1,112 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import java.net.InetAddress; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.type.SqlTypes; +import org.hibernate.type.descriptor.ValueBinder; +import org.hibernate.type.descriptor.ValueExtractor; +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.jdbc.BasicBinder; +import org.hibernate.type.descriptor.jdbc.BasicExtractor; +import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; +import org.hibernate.type.descriptor.jdbc.JdbcType; + +/** + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLCastingInetJdbcType. + */ +public class GaussDBCastingInetJdbcType implements JdbcType { + + public static final GaussDBCastingInetJdbcType INSTANCE = new GaussDBCastingInetJdbcType(); + + @Override + public void appendWriteExpression( + String writeExpression, + SqlAppender appender, + Dialect dialect) { + appender.append( "cast(" ); + appender.append( writeExpression ); + appender.append( " as inet)" ); + } + + @Override + public int getJdbcTypeCode() { + return SqlTypes.VARBINARY; + } + + @Override + public int getDefaultSqlTypeCode() { + return SqlTypes.INET; + } + + @Override + public String toString() { + return "InetSecondJdbcType"; + } + + @Override + public JdbcLiteralFormatter getJdbcLiteralFormatter(JavaType javaType) { + // No literal support for now + return null; + } + + @Override + public ValueBinder getBinder(JavaType javaType) { + return new BasicBinder<>( javaType, this ) { + @Override + protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) + throws SQLException { + st.setString( index, getStringValue( value, options ) ); + } + + @Override + protected void doBind(CallableStatement st, X value, String name, WrapperOptions options) + throws SQLException { + st.setString( name, getStringValue( value, options ) ); + } + + private String getStringValue(X value, WrapperOptions options) { + return getJavaType().unwrap( value, InetAddress.class, options ).getHostAddress(); + } + }; + } + + @Override + public ValueExtractor getExtractor(JavaType javaType) { + return new BasicExtractor<>( javaType, this ) { + @Override + protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException { + return getObject( rs.getString( paramIndex ), options ); + } + + @Override + protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException { + return getObject( statement.getString( index ), options ); + } + + @Override + protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException { + return getObject( statement.getString( name ), options ); + } + + private X getObject(String inetString, WrapperOptions options) throws SQLException { + if ( inetString == null ) { + return null; + } + return getJavaType().wrap( inetString, options ); + } + }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingIntervalSecondJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingIntervalSecondJdbcType.java new file mode 100644 index 000000000000..d64a82cfe8d3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingIntervalSecondJdbcType.java @@ -0,0 +1,154 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import java.math.BigDecimal; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.metamodel.mapping.JdbcMappingContainer; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression; +import org.hibernate.type.SqlTypes; +import org.hibernate.type.descriptor.ValueBinder; +import org.hibernate.type.descriptor.ValueExtractor; +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.jdbc.AdjustableJdbcType; +import org.hibernate.type.descriptor.jdbc.BasicBinder; +import org.hibernate.type.descriptor.jdbc.BasicExtractor; +import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; +import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; + +/** + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLCastingIntervalSecondJdbcType. + */ +public class GaussDBCastingIntervalSecondJdbcType implements AdjustableJdbcType { + + public static final GaussDBCastingIntervalSecondJdbcType INSTANCE = new GaussDBCastingIntervalSecondJdbcType(); + + @Override + public JdbcType resolveIndicatedType(JdbcTypeIndicators indicators, JavaType domainJtd) { + final int scale = indicators.getColumnScale() == JdbcTypeIndicators.NO_COLUMN_SCALE + ? domainJtd.getDefaultSqlScale( indicators.getDialect(), this ) + : indicators.getColumnScale(); + if ( scale > 6 ) { + // Since the maximum allowed scale on GaussDB is 6 (microsecond precision), + // we have to switch to the numeric type if the value is greater + return indicators.getTypeConfiguration().getJdbcTypeRegistry().getDescriptor( SqlTypes.NUMERIC ); + } + else { + return this; + } + } + + @Override + public Expression wrapTopLevelSelectionExpression(Expression expression) { + return new SelfRenderingExpression() { + @Override + public void renderToSql( + SqlAppender sqlAppender, + SqlAstTranslator walker, + SessionFactoryImplementor sessionFactory) { + sqlAppender.append( "extract(epoch from " ); + expression.accept( walker ); + sqlAppender.append( ')' ); + } + + @Override + public JdbcMappingContainer getExpressionType() { + return expression.getExpressionType(); + } + }; + } + + @Override + public void appendWriteExpression( + String writeExpression, + SqlAppender appender, + Dialect dialect) { + appender.append( '(' ); + appender.append( writeExpression ); + appender.append( "*interval'1 second')" ); + } + + @Override + public int getJdbcTypeCode() { + return SqlTypes.NUMERIC; + } + + @Override + public int getDefaultSqlTypeCode() { + return SqlTypes.INTERVAL_SECOND; + } + + @Override + public String toString() { + return "IntervalSecondJdbcType"; + } + + @Override + public JdbcLiteralFormatter getJdbcLiteralFormatter(JavaType javaType) { + // No literal support for now + return null; + } + + @Override + public ValueBinder getBinder(JavaType javaType) { + return new BasicBinder<>( javaType, this ) { + @Override + protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) + throws SQLException { + st.setBigDecimal( index, getBigDecimalValue( value, options ) ); + } + + @Override + protected void doBind(CallableStatement st, X value, String name, WrapperOptions options) + throws SQLException { + st.setBigDecimal( name, getBigDecimalValue( value, options ) ); + } + + private BigDecimal getBigDecimalValue(X value, WrapperOptions options) { + return getJavaType().unwrap( value, BigDecimal.class, options ).movePointLeft( 9 ); + } + }; + } + + @Override + public ValueExtractor getExtractor(JavaType javaType) { + return new BasicExtractor<>( javaType, this ) { + @Override + protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException { + return getObject( rs.getBigDecimal( paramIndex ), options ); + } + + @Override + protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException { + return getObject( statement.getBigDecimal( index ), options ); + } + + @Override + protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException { + return getObject( statement.getBigDecimal( name ), options ); + } + + private X getObject(BigDecimal bigDecimal, WrapperOptions options) throws SQLException { + if ( bigDecimal == null ) { + return null; + } + return getJavaType().wrap( bigDecimal.movePointRight( 9 ), options ); + } + }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingJsonArrayJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingJsonArrayJdbcType.java new file mode 100644 index 000000000000..dc7e855a1eac --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingJsonArrayJdbcType.java @@ -0,0 +1,41 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.descriptor.jdbc.JsonArrayJdbcType; + +/** + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLCastingJsonArrayJdbcType. + */ +public class GaussDBCastingJsonArrayJdbcType extends JsonArrayJdbcType { + + private final boolean jsonb; + + public GaussDBCastingJsonArrayJdbcType(JdbcType elementJdbcType, boolean jsonb) { + super( elementJdbcType ); + this.jsonb = jsonb; + } + + @Override + public void appendWriteExpression( + String writeExpression, + SqlAppender appender, + Dialect dialect) { + appender.append( "cast(" ); + appender.append( writeExpression ); + appender.append( " as " ); + if ( jsonb ) { + appender.append( "jsonb)" ); + } + else { + appender.append( "json)" ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingJsonArrayJdbcTypeConstructor.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingJsonArrayJdbcTypeConstructor.java new file mode 100644 index 000000000000..e0ec3c638ec4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingJsonArrayJdbcTypeConstructor.java @@ -0,0 +1,54 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; +import org.hibernate.type.BasicType; +import org.hibernate.type.SqlTypes; +import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * Factory for {@link GaussDBCastingJsonArrayJdbcType}. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLCastingJsonArrayJdbcTypeConstructor. + */ +public class GaussDBCastingJsonArrayJdbcTypeConstructor implements JdbcTypeConstructor { + + public static final GaussDBCastingJsonArrayJdbcTypeConstructor JSONB_INSTANCE = new GaussDBCastingJsonArrayJdbcTypeConstructor( true ); + public static final GaussDBCastingJsonArrayJdbcTypeConstructor JSON_INSTANCE = new GaussDBCastingJsonArrayJdbcTypeConstructor( false ); + + private final boolean jsonb; + + public GaussDBCastingJsonArrayJdbcTypeConstructor(boolean jsonb) { + this.jsonb = jsonb; + } + + @Override + public JdbcType resolveType( + TypeConfiguration typeConfiguration, + Dialect dialect, + BasicType elementType, + ColumnTypeInformation columnTypeInformation) { + return resolveType( typeConfiguration, dialect, elementType.getJdbcType(), columnTypeInformation ); + } + + @Override + public JdbcType resolveType( + TypeConfiguration typeConfiguration, + Dialect dialect, + JdbcType elementType, + ColumnTypeInformation columnTypeInformation) { + return new GaussDBCastingJsonArrayJdbcType( elementType, jsonb ); + } + + @Override + public int getDefaultSqlTypeCode() { + return SqlTypes.JSON_ARRAY; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingJsonJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingJsonJdbcType.java new file mode 100644 index 000000000000..00f22fe669c2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBCastingJsonJdbcType.java @@ -0,0 +1,60 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import org.hibernate.metamodel.mapping.EmbeddableMappingType; +import org.hibernate.metamodel.spi.RuntimeModelCreationContext; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.type.SqlTypes; +import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; +import org.hibernate.type.descriptor.jdbc.JsonJdbcType; + +/** + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLCastingJsonJdbcType. + */ +public class GaussDBCastingJsonJdbcType extends JsonJdbcType { + + public static final GaussDBCastingJsonJdbcType JSON_INSTANCE = new GaussDBCastingJsonJdbcType( false, null ); + public static final GaussDBCastingJsonJdbcType JSONB_INSTANCE = new GaussDBCastingJsonJdbcType( true, null ); + + private final boolean jsonb; + + public GaussDBCastingJsonJdbcType(boolean jsonb, EmbeddableMappingType embeddableMappingType) { + super( embeddableMappingType ); + this.jsonb = jsonb; + } + + @Override + public int getDdlTypeCode() { + return SqlTypes.JSON; + } + + @Override + public AggregateJdbcType resolveAggregateJdbcType( + EmbeddableMappingType mappingType, + String sqlType, + RuntimeModelCreationContext creationContext) { + return new GaussDBCastingJsonJdbcType( jsonb, mappingType ); + } + + @Override + public void appendWriteExpression( + String writeExpression, + SqlAppender appender, + Dialect dialect) { + appender.append( "cast(" ); + appender.append( writeExpression ); + appender.append( " as " ); + if ( jsonb ) { + appender.append( "jsonb)" ); + } + else { + appender.append( "json)" ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBDialect.java new file mode 100644 index 000000000000..ac399819b5ea --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBDialect.java @@ -0,0 +1,1507 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import java.sql.CallableStatement; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAccessor; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.hibernate.Length; +import org.hibernate.LockMode; +import org.hibernate.LockOptions; +import org.hibernate.PessimisticLockException; +import org.hibernate.QueryTimeoutException; +import org.hibernate.boot.model.FunctionContributions; +import org.hibernate.boot.model.TypeContributions; +import org.hibernate.dialect.aggregate.AggregateSupport; +import org.hibernate.dialect.aggregate.GaussDBAggregateSupport; +import org.hibernate.dialect.function.CommonFunctionFactory; +import org.hibernate.dialect.function.GaussDBMinMaxFunction; +import org.hibernate.dialect.function.GaussDBTruncFunction; +import org.hibernate.dialect.function.GaussDBTruncRoundFunction; +import org.hibernate.dialect.identity.IdentityColumnSupport; +import org.hibernate.dialect.identity.GaussDBIdentityColumnSupport; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.OffsetFetchLimitHandler; +import org.hibernate.dialect.sequence.GaussDBSequenceSupport; +import org.hibernate.dialect.sequence.SequenceSupport; +import org.hibernate.dialect.unique.CreateTableUniqueDelegate; +import org.hibernate.dialect.unique.UniqueDelegate; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; +import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy; +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.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.util.JdbcExceptionHelper; +import org.hibernate.mapping.AggregateColumn; +import org.hibernate.mapping.Table; +import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.metamodel.spi.RuntimeModelCreationContext; +import org.hibernate.persister.entity.mutation.EntityMutationTarget; +import org.hibernate.procedure.internal.GaussDBCallableStatementSupport; +import org.hibernate.procedure.spi.CallableStatementSupport; +import org.hibernate.query.SemanticException; +import org.hibernate.query.spi.QueryOptions; +import org.hibernate.query.sqm.CastType; +import org.hibernate.query.common.FetchClauseType; +import org.hibernate.query.sqm.IntervalType; +import org.hibernate.query.common.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.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.SqlAstTranslatorFactory; +import org.hibernate.sql.ast.spi.ParameterMarkerStrategy; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory; +import org.hibernate.sql.ast.tree.Statement; +import org.hibernate.sql.exec.spi.JdbcOperation; +import org.hibernate.sql.model.MutationOperation; +import org.hibernate.sql.model.internal.OptionalTableUpdate; +import org.hibernate.sql.model.jdbc.OptionalTableUpdateOperation; +import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; +import org.hibernate.tool.schema.internal.StandardTableExporter; +import org.hibernate.tool.schema.spi.Exporter; +import org.hibernate.type.JavaObjectType; +import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; +import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.descriptor.jdbc.ObjectNullAsBinaryTypeJdbcType; +import org.hibernate.type.descriptor.jdbc.SqlTypedJdbcType; +import org.hibernate.type.descriptor.jdbc.XmlJdbcType; +import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.ArrayDdlTypeImpl; +import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; +import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; +import org.hibernate.type.descriptor.sql.internal.NamedNativeEnumDdlTypeImpl; +import org.hibernate.type.descriptor.sql.internal.NamedNativeOrdinalEnumDdlTypeImpl; +import org.hibernate.type.descriptor.sql.internal.Scale6IntervalSecondDdlType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; +import org.hibernate.type.spi.TypeConfiguration; + +import jakarta.persistence.GenerationType; +import jakarta.persistence.TemporalType; + +import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate; +import static org.hibernate.query.common.TemporalUnit.DAY; +import static org.hibernate.query.common.TemporalUnit.EPOCH; +import static org.hibernate.type.SqlTypes.ARRAY; +import static org.hibernate.type.SqlTypes.BINARY; +import static org.hibernate.type.SqlTypes.CHAR; +import static org.hibernate.type.SqlTypes.FLOAT; +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.JSON; +import static org.hibernate.type.SqlTypes.LONG32NVARCHAR; +import static org.hibernate.type.SqlTypes.LONG32VARBINARY; +import static org.hibernate.type.SqlTypes.LONG32VARCHAR; +import static org.hibernate.type.SqlTypes.NCHAR; +import static org.hibernate.type.SqlTypes.NCLOB; +import static org.hibernate.type.SqlTypes.NVARCHAR; +import static org.hibernate.type.SqlTypes.OTHER; +import static org.hibernate.type.SqlTypes.SQLXML; +import static org.hibernate.type.SqlTypes.STRUCT; +import static org.hibernate.type.SqlTypes.TIME; +import static org.hibernate.type.SqlTypes.TIMESTAMP; +import static org.hibernate.type.SqlTypes.TIMESTAMP_UTC; +import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; +import static org.hibernate.type.SqlTypes.TIME_UTC; +import static org.hibernate.type.SqlTypes.TINYINT; +import static org.hibernate.type.SqlTypes.UUID; +import static org.hibernate.type.SqlTypes.VARBINARY; +import static org.hibernate.type.SqlTypes.VARCHAR; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsLocalTime; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros; +import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMillis; + +/** + * A {@linkplain Dialect SQL dialect} for GaussDB V2.0-8.201 and above. + *

+ * Please refer to the + * GaussDB documentation. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLDialect. + */ +public class GaussDBDialect extends Dialect { + protected final static DatabaseVersion MINIMUM_VERSION = DatabaseVersion.make( 2 ); + + private final UniqueDelegate uniqueDelegate = new CreateTableUniqueDelegate(this); + private final StandardTableExporter gaussDBTableExporter = new StandardTableExporter( this ) { + @Override + protected void applyAggregateColumnCheck(StringBuilder buf, AggregateColumn aggregateColumn) { + final JdbcType jdbcType = aggregateColumn.getType().getJdbcType(); + if ( jdbcType.isXml() ) { + // Requires the use of xmltable which is not supported in check constraints + return; + } + super.applyAggregateColumnCheck( buf, aggregateColumn ); + } + }; + + private final OptionalTableUpdateStrategy optionalTableUpdateStrategy; + + public GaussDBDialect() { + this(MINIMUM_VERSION); + } + + public GaussDBDialect(DialectResolutionInfo info) { + this( info.makeCopyOrDefault( MINIMUM_VERSION )); + registerKeywords( info ); + } + + public GaussDBDialect(DatabaseVersion version) { + super( version ); + this.optionalTableUpdateStrategy = determineOptionalTableUpdateStrategy( version ); + } + + public boolean supportsColumnCheck() { + return false; + } + + private static OptionalTableUpdateStrategy determineOptionalTableUpdateStrategy(DatabaseVersion version) { + return version.isSameOrAfter( DatabaseVersion.make( 15, 0 ) ) + ? GaussDBDialect::usingMerge + : GaussDBDialect::withoutMerge; + } + + @Override + protected DatabaseVersion getMinimumSupportedVersion() { + return MINIMUM_VERSION; + } + + @Override + public boolean getDefaultNonContextualLobCreation() { + return true; + } + + @Override + protected String columnType(int sqlTypeCode) { + return switch (sqlTypeCode) { + // no tinyint + case TINYINT -> "smallint"; + + // there are no nchar/nvarchar types + case NCHAR -> columnType( CHAR ); + case NVARCHAR -> columnType( VARCHAR ); + + case LONG32VARCHAR, LONG32NVARCHAR -> "text"; + case NCLOB -> "clob"; + + case BINARY, VARBINARY, LONG32VARBINARY -> "bytea"; + + case TIMESTAMP_UTC -> columnType( TIMESTAMP_WITH_TIMEZONE ); + + default -> super.columnType( sqlTypeCode ); + }; + } + + @Override + protected String castType(int sqlTypeCode) { + return switch (sqlTypeCode) { + case CHAR, NCHAR, VARCHAR, NVARCHAR -> "varchar"; + case LONG32VARCHAR, LONG32NVARCHAR -> "text"; + case NCLOB -> "clob"; + case BINARY, VARBINARY, LONG32VARBINARY -> "bytea"; + default -> super.castType( sqlTypeCode ); + }; + } + + @Override + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + + // We need to configure that the array type uses the raw element type for casts + ddlTypeRegistry.addDescriptor( new ArrayDdlTypeImpl( this, true ) ); + + // Register this type to be able to support Float[] + // The issue is that the JDBC driver can't handle createArrayOf( "float(24)", ... ) + // It requires the use of "real" or "float4" + // Alternatively we could introduce a new API in Dialect for creating such base names + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( FLOAT, columnType( FLOAT ), castType( FLOAT ), this ) + .withTypeCapacity( 24, "float4" ) + .build() + ); + + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( SQLXML, "xml", this ) ); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( UUID, "uuid", this ) ); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( INET, "inet", this ) ); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "geometry", this ) ); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOGRAPHY, "geography", this ) ); + ddlTypeRegistry.addDescriptor( new Scale6IntervalSecondDdlType( this ) ); + + // Prefer jsonb if possible + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "jsonb", this ) ); + + ddlTypeRegistry.addDescriptor( new NamedNativeEnumDdlTypeImpl( this ) ); + ddlTypeRegistry.addDescriptor( new NamedNativeOrdinalEnumDdlTypeImpl( this ) ); + } + + @Override + public int getMaxVarcharLength() { + return 10_485_760; + } + + @Override + public int getMaxVarcharCapacity() { + // 1GB-85-4 according to GaussDB docs + return 1_073_741_727; + } + + @Override + public int getMaxVarbinaryLength() { + //has no varbinary-like type + return Length.LONG32; + } + + @Override + public int getDefaultStatementBatchSize() { + return 15; + } + + @Override + public JdbcType resolveSqlTypeDescriptor( + String columnTypeName, + int jdbcTypeCode, + int precision, + int scale, + JdbcTypeRegistry jdbcTypeRegistry) { + switch ( jdbcTypeCode ) { + case OTHER: + switch ( columnTypeName ) { + case "uuid": + jdbcTypeCode = UUID; + break; + case "json": + case "jsonb": + jdbcTypeCode = JSON; + break; + case "xml": + jdbcTypeCode = SQLXML; + break; + case "inet": + jdbcTypeCode = INET; + break; + case "geometry": + jdbcTypeCode = GEOMETRY; + break; + case "geography": + jdbcTypeCode = GEOGRAPHY; + break; + } + break; + case TIME: + // The GaussDB JDBC driver reports TIME for timetz, but we use it only for mapping OffsetTime to UTC + if ( "timetz".equals( columnTypeName ) ) { + jdbcTypeCode = TIME_UTC; + } + break; + case TIMESTAMP: + // The GaussDB JDBC driver reports TIMESTAMP for timestamptz, but we use it only for mapping Instant + if ( "timestamptz".equals( columnTypeName ) ) { + jdbcTypeCode = TIMESTAMP_UTC; + } + break; + case ARRAY: + // GaussDB names array types by prepending an underscore to the base name + if ( columnTypeName.charAt( 0 ) == '_' ) { + final String componentTypeName = columnTypeName.substring( 1 ); + final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() ); + if ( sqlTypeCode != null ) { + return jdbcTypeRegistry.resolveTypeConstructorDescriptor( + jdbcTypeCode, + jdbcTypeRegistry.getDescriptor( sqlTypeCode ), + ColumnTypeInformation.EMPTY + ); + } + final SqlTypedJdbcType elementDescriptor = jdbcTypeRegistry.findSqlTypedDescriptor( componentTypeName ); + if ( elementDescriptor != null ) { + return jdbcTypeRegistry.resolveTypeConstructorDescriptor( + jdbcTypeCode, + elementDescriptor, + ColumnTypeInformation.EMPTY + ); + } + } + break; + case STRUCT: + final SqlTypedJdbcType descriptor = jdbcTypeRegistry.findSqlTypedDescriptor( + // Skip the schema + columnTypeName.substring( columnTypeName.indexOf( '.' ) + 1 ) + ); + if ( descriptor != null ) { + return descriptor; + } + break; + } + return jdbcTypeRegistry.getDescriptor( jdbcTypeCode ); + } + + @Override + protected Integer resolveSqlTypeCode(String columnTypeName, TypeConfiguration typeConfiguration) { + return switch (columnTypeName) { + case "bool" -> Types.BOOLEAN; + case "float4" -> Types.REAL; // Use REAL instead of FLOAT to get Float as recommended Java type + case "float8" -> Types.DOUBLE; + case "int2" -> Types.SMALLINT; + case "int4" -> Types.INTEGER; + case "int8" -> Types.BIGINT; + default -> super.resolveSqlTypeCode( columnTypeName, typeConfiguration ); + }; + } + + @Override + public String getEnumTypeDeclaration(String name, String[] values) { + return name; + } + + @Override + public String[] getCreateEnumTypeCommand(String name, String[] values) { + StringBuilder type = new StringBuilder(); + type.append( "create type " ) + .append( name ) + .append( " as enum (" ); + String separator = ""; + for ( String value : values ) { + type.append( separator ).append('\'').append( value ).append('\''); + separator = ","; + } + type.append( ')' ); + String cast1 = "create cast (varchar as " + + name + + ") with inout as implicit"; + String cast2 = "create cast (" + + name + + " as varchar) with inout as implicit"; + return new String[] { type.toString(), cast1, cast2 }; + } + + @Override + public String[] getDropEnumTypeCommand(String name) { + return new String[] { "drop type if exists " + name + " cascade" }; + } + + @Override + public String currentTime() { + return "localtime"; + } + + @Override + public String currentTimestamp() { + return "localtimestamp"; + } + + @Override + public String currentTimestampWithTimeZone() { + return "current_timestamp"; + } + + /** + * The {@code extract()} function returns {@link TemporalUnit#DAY_OF_WEEK} + * numbered from 0 to 6. This isn't consistent with what most other + * databases do, so here we adjust the result by generating + * {@code (extract(dow,arg)+1))}. + */ + @Override + public String extractPattern(TemporalUnit unit) { + return switch (unit) { + case DAY_OF_WEEK -> "(" + super.extractPattern( unit ) + "+1)"; + default -> super.extractPattern(unit); + }; + } + + @Override + public String castPattern(CastType from, CastType to) { + if ( from == CastType.STRING && to == CastType.BOOLEAN ) { + return "cast(?1 as ?2)"; + } + else { + return super.castPattern( from, to ); + } + } + + /** + * {@code microsecond} is the smallest unit for an {@code interval}, + * and the highest precision for a {@code timestamp}, so we could + * use it as the "native" precision, but it's more convenient to use + * whole seconds (with the fractional part), since we want to use + * {@code extract(epoch from ...)} in our emulation of + * {@code timestampdiff()}. + */ + @Override + public long getFractionalSecondPrecisionInNanos() { + return 1_000_000_000; //seconds + } + + @Override @SuppressWarnings("deprecation") + public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) { + return intervalType != null + ? "(?2+?3)" + : "cast(?3+" + intervalPattern( unit ) + " as " + temporalType.name().toLowerCase() + ")"; + } + + private static String intervalPattern(TemporalUnit unit) { + return switch (unit) { + case NANOSECOND -> "(?2)/1e3*interval '1 microsecond'"; + case NATIVE -> "(?2)*interval '1 second'"; + case QUARTER -> "(?2)*interval '3 month'"; // quarter is not supported in interval literals + case WEEK -> "(?2)*interval '7 day'"; // week is not supported in interval literals + default -> "(?2)*interval '1 " + unit + "'"; + }; + } + + @Override @SuppressWarnings("deprecation") + public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalType, TemporalType toTemporalType) { + if ( unit == null ) { + return "(?3-?2)"; + } + if ( toTemporalType == TemporalType.DATE && fromTemporalType == TemporalType.DATE ) { + // special case: subtraction of two dates + // results in an integer number of days + // instead of an INTERVAL + return switch (unit) { + case YEAR, MONTH, QUARTER -> "extract(" + translateDurationField( unit ) + " from age(?3,?2))"; + default -> "(?3-?2)" + DAY.conversionFactor( unit, this ); + }; + } + else { + return switch (unit) { + case YEAR -> "extract(year from ?3-?2)"; + case QUARTER -> "(extract(year from ?3-?2)*4+extract(month from ?3-?2)/3)"; + case MONTH -> "(extract(year from ?3-?2)*12+extract(month from ?3-?2))"; + case WEEK -> "(extract(day from ?3-?2)/7)"; // week is not supported by extract() when the argument is a duration + case DAY -> "extract(day from ?3-?2)"; + // in order to avoid multiple calls to extract(), + // we use extract(epoch from x - y) * factor for + // all the following units: + case HOUR, MINUTE, SECOND, NANOSECOND, NATIVE -> + "extract(epoch from ?3-?2)" + EPOCH.conversionFactor( unit, this ); + default -> throw new SemanticException( "Unrecognized field: " + unit ); + }; + } + } + + @Override + public TimeZoneSupport getTimeZoneSupport() { + return TimeZoneSupport.NORMALIZE; + } + + @Override + public void initializeFunctionRegistry(FunctionContributions functionContributions) { + super.initializeFunctionRegistry(functionContributions); + + CommonFunctionFactory functionFactory = new CommonFunctionFactory(functionContributions); + + functionFactory.cot(); + functionFactory.radians(); + functionFactory.degrees(); + functionFactory.log(); + functionFactory.mod_operator(); + functionFactory.log10(); + functionFactory.tanh(); + functionFactory.sinh(); + functionFactory.cosh(); + functionFactory.moreHyperbolic(); + functionFactory.cbrt(); + functionFactory.pi(); + functionFactory.trim2(); + functionFactory.repeat(); + functionFactory.initcap(); + functionFactory.substr(); + functionFactory.substring_substr(); + //also natively supports ANSI-style substring() + functionFactory.translate(); + functionFactory.toCharNumberDateTimestamp(); + functionFactory.localtimeLocaltimestamp(); + functionFactory.bitLength_pattern( "bit_length(?1)", "length(?1)*8" ); + functionFactory.octetLength_pattern( "octet_length(?1)", "length(?1)" ); + functionFactory.ascii(); + functionFactory.char_chr(); + functionFactory.position(); + functionFactory.bitandorxornot_operator(); + functionFactory.bitAndOr(); + functionFactory.everyAny_boolAndOr(); + functionFactory.median_percentileCont( false ); + functionFactory.stddev(); + functionFactory.stddevPopSamp(); + functionFactory.variance(); + functionFactory.varPopSamp(); + functionFactory.covarPopSamp(); + functionFactory.corr(); + functionFactory.regrLinearRegressionAggregates(); + functionFactory.insert_overlay(); + functionFactory.overlay(); + functionFactory.soundex(); //was introduced apparently + functionFactory.format_toChar_gauss(); + + functionFactory.locate_positionSubstring(); + functionFactory.windowFunctions(); + functionFactory.listagg_stringAgg( "varchar" ); + functionFactory.array_gaussdb(); + functionFactory.arrayAggregate(); + functionFactory.arrayRemoveIndex_gaussdb(); + functionFactory.arrayLength_cardinality(); + functionFactory.arrayConcat_gaussdb(); + functionFactory.arrayPrepend_gaussdb(); + functionFactory.arrayAppend_gaussdb(); + functionFactory.arrayContains_gaussdb(); + functionFactory.arrayIntersects_gaussdb(); + functionFactory.arrayGet_bracket(); + functionFactory.arrayRemove_gaussdb(); + functionFactory.arraySlice_operator(); + functionFactory.arrayReplace_gaussdb(); + functionFactory.arraySet_gaussdb(); + functionFactory.arrayTrim_gaussdb(); + functionFactory.arrayFill_gaussdb(); + functionFactory.arrayPosition_gaussdb(); + + functionFactory.jsonValue_gaussdb(true); + functionFactory.jsonQuery_gaussdb(); + functionFactory.jsonExists_gaussdb(); + functionFactory.jsonArray(); + functionFactory.jsonObject_gaussdb(); + functionFactory.jsonArrayAgg_gaussdb( true ); + functionFactory.jsonObjectAgg_gaussdb( true ); + functionFactory.jsonTable(); + + functionFactory.jsonSet_gaussdb(); + functionFactory.jsonRemove_gaussdb(); + functionFactory.jsonReplace_gaussdb(); + functionFactory.jsonInsert_gaussdb(); + functionFactory.jsonArray_gaussdb(); + functionFactory.jsonMergepatch_gaussdb(); + functionFactory.jsonArrayInsert_gauss(); + + functionFactory.xmlelement(); + functionFactory.xmlcomment(); + functionFactory.xmlforest(); + functionFactory.xmlconcat(); + functionFactory.xmlpi(); + functionFactory.xmlquery_gaussdb(); + functionFactory.xmlexists(); + functionFactory.xmlagg(); + functionFactory.xmltable( true ); + + functionFactory.makeDateTimeTimestamp(); + // Note that GaussDB doesn't support the OVER clause for ordered set-aggregate functions + functionFactory.inverseDistributionOrderedSetAggregates(); + functionFactory.hypotheticalOrderedSetAggregates(); + + if ( !supportsMinMaxOnUuid() ) { + functionContributions.getFunctionRegistry().register( "min", new GaussDBMinMaxFunction( "min" ) ); + functionContributions.getFunctionRegistry().register( "max", new GaussDBMinMaxFunction( "max" ) ); + } + + // uses # instead of ^ for XOR + functionContributions.getFunctionRegistry().patternDescriptorBuilder( "bitxor", "(?1 # ?2)" ) + .setExactArgumentCount( 2 ) + .setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE ) + .register(); + + functionContributions.getFunctionRegistry().register( + "round", new GaussDBTruncRoundFunction( "round", true ) + ); + functionContributions.getFunctionRegistry().register( + "trunc", + new GaussDBTruncFunction( true, functionContributions.getTypeConfiguration() ) + ); + functionContributions.getFunctionRegistry().registerAlternateKey( "truncate", "trunc" ); + functionFactory.dateTrunc(); + + functionFactory.unnest( null, "ordinality" ); + + functionFactory.hex( "encode(?1, 'hex')" ); + functionFactory.sha( "sha256(?1)" ); + functionFactory.md5( "decode(md5(?1), 'hex')" ); + } + + @Override + public @Nullable String getDefaultOrdinalityColumnName() { + return "ordinality"; + } + + /** + * Whether GaussDB supports {@code min(uuid)}/{@code max(uuid)}, + * which it doesn't by default. Since the emulation does not perform well, + * this method may be overridden by any user who ensures that aggregate + * functions for handling uuids exist in the database. + *

+ * The following definitions can be used for this purpose: + *

+	 * create or replace function min(uuid, uuid)
+	 *     returns uuid
+	 *     immutable parallel safe
+	 *     language plpgsql as
+	 * $$
+	 * begin
+	 *     return least($1, $2);
+	 * end
+	 * $$;
+	 *
+	 * create aggregate min(uuid) (
+	 *     sfunc = min,
+	 *     stype = uuid,
+	 *     combinefunc = min,
+	 *     parallel = safe,
+	 *     sortop = operator (<)
+	 *     );
+	 *
+	 * create or replace function max(uuid, uuid)
+	 *     returns uuid
+	 *     immutable parallel safe
+	 *     language plpgsql as
+	 * $$
+	 * begin
+	 *     return greatest($1, $2);
+	 * end
+	 * $$;
+	 *
+	 * create aggregate max(uuid) (
+	 *     sfunc = max,
+	 *     stype = uuid,
+	 *     combinefunc = max,
+	 *     parallel = safe,
+	 *     sortop = operator (>)
+	 *     );
+	 * 
+ */ + protected boolean supportsMinMaxOnUuid() { + return false; + } + + @Override + public NameQualifierSupport getNameQualifierSupport() { + // This method is overridden so the correct value will be returned when + // DatabaseMetaData is not available. + return NameQualifierSupport.SCHEMA; + } + + @Override + public String getCurrentSchemaCommand() { + return "select current_schema()"; + } + + @Override + public boolean supportsDistinctFromPredicate() { + return true; + } + + @Override + public boolean supportsIfExistsBeforeTableName() { + return true; + } + + @Override + public boolean supportsIfExistsBeforeTypeName() { + return true; + } + + @Override + public boolean supportsIfExistsBeforeConstraintName() { + return true; + } + + @Override + public boolean supportsIfExistsAfterAlterTable() { + return true; + } + + @Override + public String getBeforeDropStatement() { + // NOTICE: table "nonexistent" does not exist, skipping + // as a JDBC SQLWarning + return "set client_min_messages = WARNING"; + } + + @Override + public String getAlterColumnTypeString(String columnName, String columnType, String columnDefinition) { + // would need multiple statements to 'set not null'/'drop not null', 'set default'/'drop default', 'set generated', etc + return "alter column " + columnName + " set data type " + columnType; + } + + @Override + public boolean supportsAlterColumnType() { + return true; + } + + @Override + public boolean supportsValuesList() { + return true; + } + + @Override + public boolean supportsPartitionBy() { + return true; + } + + @Override + public boolean supportsNonQueryWithCTE() { + return true; + } + @Override + public boolean supportsConflictClauseForInsertCTE() { + return true; + } + + @Override + public SequenceSupport getSequenceSupport() { + return GaussDBSequenceSupport.INSTANCE; + } + + @Override + public String getCascadeConstraintsString() { + return " cascade"; + } + + @Override + public String getQuerySequencesString() { + return "select * from information_schema.sequences"; + } + + @Override + public LimitHandler getLimitHandler() { + return OffsetFetchLimitHandler.INSTANCE; + } + + @Override + public String getForUpdateString(String aliases) { + return getForUpdateString() + " of " + aliases; + } + + @Override + public String getForUpdateString(String aliases, LockOptions lockOptions) { + // parent's implementation for (aliases, lockOptions) ignores aliases + if ( aliases.isEmpty() ) { + LockMode lockMode = lockOptions.getLockMode(); + for ( Map.Entry entry : lockOptions.getAliasSpecificLocks() ) { + // seek the highest lock mode + if ( entry.getValue().greaterThan(lockMode) ) { + aliases = entry.getKey(); + } + } + } + LockMode lockMode = lockOptions.getAliasSpecificLockMode( aliases ); + if ( lockMode == null ) { + lockMode = lockOptions.getLockMode(); + } + return switch (lockMode) { + case PESSIMISTIC_READ -> getReadLockString( aliases, lockOptions.getTimeOut() ); + case PESSIMISTIC_WRITE -> getWriteLockString( aliases, lockOptions.getTimeOut() ); + case UPGRADE_NOWAIT, PESSIMISTIC_FORCE_INCREMENT -> getForUpdateNowaitString( aliases ); + case UPGRADE_SKIPLOCKED -> getForUpdateSkipLockedString( aliases ); + default -> ""; + }; + } + + @Override + public String getNoColumnsInsertString() { + return "default values"; + } + + @Override + public String getCaseInsensitiveLike(){ + return "ilike"; + } + + @Override + public boolean supportsCaseInsensitiveLike() { + return true; + } + + @Override + public GenerationType getNativeValueGenerationStrategy() { + return GenerationType.SEQUENCE; + } + + @Override + public boolean supportsOuterJoinForUpdate() { + return false; + } + + @Override + public boolean useInputStreamToInsertBlob() { + return false; + } + + @Override + public boolean useConnectionToCreateLob() { + return false; + } + + @Override + public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) { + // TODO: adapt this to handle named enum types! + return "cast(null as " + typeConfiguration.getDdlTypeRegistry().getDescriptor( sqlType ).getRawTypeName() + ")"; + } + + @Override + public String quoteCollation(String collation) { + return '\"' + collation + '\"'; + } + + @Override + public boolean supportsCommentOn() { + return true; + } + + @Override + public boolean supportsCurrentTimestampSelection() { + return true; + } + + @Override + public boolean isCurrentTimestampSelectStringCallable() { + return false; + } + + @Override + public String getCurrentTimestampSelectString() { + return "select now()"; + } + + @Override + public boolean supportsTupleCounts() { + return true; + } + + @Override + public boolean supportsIsTrue() { + return true; + } + + @Override + public boolean requiresParensForTupleDistinctCounts() { + return true; + } + + @Override + public void appendBooleanValueString(SqlAppender appender, boolean bool) { + appender.appendSql( bool ); + } + + @Override + public IdentifierHelper buildIdentifierHelper(IdentifierHelperBuilder builder, DatabaseMetaData dbMetaData) + throws SQLException { + + if ( dbMetaData == null ) { + builder.setUnquotedCaseStrategy( IdentifierCaseStrategy.LOWER ); + builder.setQuotedCaseStrategy( IdentifierCaseStrategy.MIXED ); + } + + return super.buildIdentifierHelper( builder, dbMetaData ); + } + + @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 ); + } + + @Override + public SqlAstTranslatorFactory getSqlAstTranslatorFactory() { + return new StandardSqlAstTranslatorFactory() { + @Override + protected SqlAstTranslator buildTranslator( + SessionFactoryImplementor sessionFactory, Statement statement) { + return new GaussDBSqlAstTranslator<>( sessionFactory, statement ); + } + }; + } + + @Override + public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() { + return EXTRACTOR; + } + + /** + * Constraint-name extractor for 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 ) { + 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; + } + } + return null; + } ); + + @Override + public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() { + return (sqlException, message, sql) -> { + final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException ); + if ( sqlState != 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 ); + } + } + return null; + }; + } + + @Override + public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException { + // Register the type of the out param - GaussDB uses Types.OTHER + statement.registerOutParameter( col++, Types.OTHER ); + return col; + } + + @Override + public ResultSet getResultSet(CallableStatement ps) throws SQLException { + ps.execute(); + return (ResultSet) ps.getObject( 1 ); + } + + // Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public boolean supportsLobValueChangePropagation() { + return false; + } + + @Override + public boolean supportsUnboundedLobLocatorMaterialization() { + return false; + } + + @Override + public SelectItemReferenceStrategy getGroupBySelectItemReferenceStrategy() { + return SelectItemReferenceStrategy.POSITION; + } + + @Override + public CallableStatementSupport getCallableStatementSupport() { + return GaussDBCallableStatementSupport.INSTANCE; + } + + @Override + public ResultSet getResultSet(CallableStatement statement, int position) throws SQLException { + if ( position != 1 ) { + throw new UnsupportedOperationException( "GaussDB only supports REF_CURSOR parameters as the first parameter" ); + } + return (ResultSet) statement.getObject( 1 ); + } + + @Override + public ResultSet getResultSet(CallableStatement statement, String name) throws SQLException { + throw new UnsupportedOperationException( "GaussDB only supports accessing REF_CURSOR parameters by position" ); + } + + @Override + public boolean qualifyIndexName() { + return false; + } + + @Override + public IdentityColumnSupport getIdentityColumnSupport() { + return GaussDBIdentityColumnSupport.INSTANCE; + } + + @Override + public NationalizationSupport getNationalizationSupport() { + return NationalizationSupport.IMPLICIT; + } + + @Override + public int getMaxIdentifierLength() { + return 63; + } + + @Override + public boolean supportsStandardArrays() { + return true; + } + + @Override + public boolean supportsJdbcConnectionLobCreation(DatabaseMetaData databaseMetaData) { + return false; + } + + @Override + public boolean supportsMaterializedLobAccess() { + // Prefer using text and bytea over oid (LOB), because oid is very restricted. + // If someone really wants a type bigger than 1GB, they should ask for it by using @Lob explicitly + return false; + } + + @Override + public boolean supportsTemporalLiteralOffset() { + return true; + } + + @Override + public void appendDatetimeFormat(SqlAppender appender, String format) { + appender.appendSql( datetimeFormat( format ).result() ); + } + + public Replacer datetimeFormat(String format) { + return OracleDialect.datetimeFormat( format, true, false ) + .replace("SSSSSS", "US") + .replace("SSSSS", "US") + .replace("SSSS", "US") + .replace("SSS", "MS") + .replace("SS", "MS") + .replace("S", "MS") + //use ISO day in week, as per DateTimeFormatter + .replace("ee", "ID") + .replace("e", "fmID") + //TZR is TZ + .replace("zzz", "TZ") + .replace("zz", "TZ") + .replace("z", "TZ") + .replace("xxx", "OF") + .replace("xx", "OF") + .replace("x", "OF"); + } + + @Override + public String translateExtractField(TemporalUnit unit) { + return switch (unit) { + //WEEK means the ISO week number + case DAY_OF_MONTH -> "day"; + case DAY_OF_YEAR -> "doy"; + case DAY_OF_WEEK -> "dow"; + default -> super.translateExtractField( unit ); + }; + } + + @Override + public AggregateSupport getAggregateSupport() { + return GaussDBAggregateSupport.valueOf( this ); + } + + @Override + public void appendBinaryLiteral(SqlAppender appender, byte[] bytes) { + appender.appendSql( "bytea '\\x" ); + PrimitiveByteArrayJavaType.INSTANCE.appendString( appender, bytes ); + appender.appendSql( '\'' ); + } + + @Override + public void appendDateTimeLiteral( + SqlAppender appender, + TemporalAccessor temporalAccessor, + @SuppressWarnings("deprecation") + TemporalType precision, + TimeZone jdbcTimeZone) { + switch ( precision ) { + case DATE: + appender.appendSql( "date '" ); + appendAsDate( appender, temporalAccessor ); + appender.appendSql( '\'' ); + break; + case TIME: + if ( supportsTemporalLiteralOffset() && temporalAccessor.isSupported( ChronoField.OFFSET_SECONDS ) ) { + appender.appendSql( "time with time zone '" ); + appendAsTime( appender, temporalAccessor, true, jdbcTimeZone ); + } + else { + appender.appendSql( "time '" ); + appendAsLocalTime( appender, temporalAccessor ); + } + appender.appendSql( '\'' ); + break; + case TIMESTAMP: + if ( supportsTemporalLiteralOffset() && temporalAccessor.isSupported( ChronoField.OFFSET_SECONDS ) ) { + appender.appendSql( "timestamp with time zone '" ); + appendAsTimestampWithMicros( appender, temporalAccessor, true, jdbcTimeZone ); + appender.appendSql( '\'' ); + } + else { + appender.appendSql( "timestamp '" ); + appendAsTimestampWithMicros( appender, temporalAccessor, false, jdbcTimeZone ); + appender.appendSql( '\'' ); + } + break; + default: + throw new IllegalArgumentException(); + } + } + + @Override + public void appendDateTimeLiteral( + SqlAppender appender, + Date date, + @SuppressWarnings("deprecation") + TemporalType precision, + TimeZone jdbcTimeZone) { + switch ( precision ) { + case DATE: + appender.appendSql( "date '" ); + appendAsDate( appender, date ); + appender.appendSql( '\'' ); + break; + case TIME: + appender.appendSql( "time with time zone '" ); + appendAsTime( appender, date, jdbcTimeZone ); + appender.appendSql( '\'' ); + break; + case TIMESTAMP: + appender.appendSql( "timestamp with time zone '" ); + appendAsTimestampWithMicros( appender, date, jdbcTimeZone ); + appender.appendSql( '\'' ); + break; + default: + throw new IllegalArgumentException(); + } + } + + @Override + public void appendDateTimeLiteral( + SqlAppender appender, + Calendar calendar, + @SuppressWarnings("deprecation") + TemporalType precision, + TimeZone jdbcTimeZone) { + switch ( precision ) { + case DATE: + appender.appendSql( "date '" ); + appendAsDate( appender, calendar ); + appender.appendSql( '\'' ); + break; + case TIME: + appender.appendSql( "time with time zone '" ); + appendAsTime( appender, calendar, jdbcTimeZone ); + appender.appendSql( '\'' ); + break; + case TIMESTAMP: + appender.appendSql( "timestamp with time zone '" ); + appendAsTimestampWithMillis( appender, calendar, jdbcTimeZone ); + appender.appendSql( '\'' ); + break; + default: + throw new IllegalArgumentException(); + } + } + + private String withTimeout(String lockString, int timeout) { + return switch (timeout) { + case LockOptions.NO_WAIT -> supportsNoWait() ? lockString + " nowait" : lockString; + case LockOptions.SKIP_LOCKED -> supportsSkipLocked() ? lockString + " skip locked" : lockString; + default -> lockString; + }; + } + + @Override + public String getWriteLockString(int timeout) { + return withTimeout( getForUpdateString(), timeout ); + } + + @Override + public String getWriteLockString(String aliases, int timeout) { + return withTimeout( getForUpdateString( aliases ), timeout ); + } + + @Override + public String getReadLockString(int timeout) { + return withTimeout(" for share", timeout ); + } + + @Override + public String getReadLockString(String aliases, int timeout) { + return withTimeout(" for share of " + aliases, timeout ); + } + + @Override + public String getForUpdateNowaitString() { + return supportsNoWait() + ? " for update nowait" + : getForUpdateString(); + } + + @Override + public String getForUpdateNowaitString(String aliases) { + return supportsNoWait() + ? " for update of " + aliases + " nowait" + : getForUpdateString(aliases); + } + + @Override + public String getForUpdateSkipLockedString() { + return supportsSkipLocked() + ? " for update skip locked" + : getForUpdateString(); + } + + @Override + public String getForUpdateSkipLockedString(String aliases) { + return supportsSkipLocked() + ? " for update of " + aliases + " skip locked" + : getForUpdateString( aliases ); + } + + @Override + public boolean supportsNoWait() { + return true; + } + + @Override + public boolean supportsWait() { + return false; + } + + @Override + public boolean supportsSkipLocked() { + return true; + } + + @Override + public boolean supportsInsertReturning() { + return true; + } + + @Override + public boolean supportsOffsetInSubquery() { + return true; + } + + @Override + public boolean supportsWindowFunctions() { + return true; + } + + @Override + public boolean supportsLateral() { + return false; + } + + @Override + public boolean supportsRecursiveCTE() { + return true; + } + + @Override + public boolean supportsFetchClause(FetchClauseType type) { + return false; + } + + @Override + public String getForUpdateString() { + return " for update"; + } + + @Override + public boolean supportsFilterClause() { + return false; + } + + @Override + public FunctionalDependencyAnalysisSupport getFunctionalDependencyAnalysisSupport() { + return FunctionalDependencyAnalysisSupportImpl.TABLE_REFERENCE; + } + + @Override + public RowLockStrategy getWriteRowLockStrategy() { + return RowLockStrategy.TABLE; + } + + @Override + public void augmentRecognizedTableTypes(List tableTypesList) { + super.augmentRecognizedTableTypes( tableTypesList ); + tableTypesList.add( "MATERIALIZED VIEW" ); + tableTypesList.add( "PARTITIONED TABLE" ); + } + + @Override + public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.contributeTypes(typeContributions, serviceRegistry); + contributeGaussDBTypes( typeContributions, serviceRegistry); + } + + /** + * Allow for extension points to override this only + */ + protected void contributeGaussDBTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration() + .getJdbcTypeRegistry(); + // For how BLOB affects Hibernate, see: + // http://in.relation.to/15492.lace + + jdbcTypeRegistry.addDescriptor( XmlJdbcType.INSTANCE ); + + jdbcTypeRegistry.addDescriptorIfAbsent( GaussDBCastingInetJdbcType.INSTANCE ); + jdbcTypeRegistry.addDescriptorIfAbsent( GaussDBCastingIntervalSecondJdbcType.INSTANCE ); + jdbcTypeRegistry.addDescriptorIfAbsent( GaussDBStructCastingJdbcType.INSTANCE ); + jdbcTypeRegistry.addDescriptorIfAbsent( GaussDBCastingJsonJdbcType.JSONB_INSTANCE ); + jdbcTypeRegistry.addTypeConstructorIfAbsent( GaussDBCastingJsonArrayJdbcTypeConstructor.JSONB_INSTANCE ); + + // GaussDB requires a custom binder for binding untyped nulls as VARBINARY + typeContributions.contributeJdbcType( ObjectNullAsBinaryTypeJdbcType.INSTANCE ); + + // Until we remove StandardBasicTypes, we have to keep this + typeContributions.contributeType( + new JavaObjectType( + ObjectNullAsBinaryTypeJdbcType.INSTANCE, + typeContributions.getTypeConfiguration() + .getJavaTypeRegistry() + .getDescriptor( Object.class ) + ) + ); + + jdbcTypeRegistry.addDescriptor( GaussDBEnumJdbcType.INSTANCE ); + jdbcTypeRegistry.addDescriptor( GaussDBOrdinalEnumJdbcType.INSTANCE ); + jdbcTypeRegistry.addDescriptor( GaussDBUUIDJdbcType.INSTANCE ); + + // Replace the standard array constructor + jdbcTypeRegistry.addTypeConstructor( GaussDBArrayJdbcTypeConstructor.INSTANCE ); + } + + @Override + public UniqueDelegate getUniqueDelegate() { + return uniqueDelegate; + } + + @Override + public Exporter getTableExporter() { + return gaussDBTableExporter; + } + + /** + * @return {@code true}, but only because we can "batch" truncate + */ + @Override + public boolean canBatchTruncate() { + return true; + } + + @Override + public String getQueryHintString(String sql, String hints) { + return "/*+ " + hints + " */ " + sql; + } + + @Override + public String addSqlHintOrComment(String sql, QueryOptions queryOptions, boolean commentsEnabled) { + // GaussDB's extension pg_hint_plan needs the hint to be the first comment + if ( commentsEnabled && queryOptions.getComment() != null ) { + sql = prependComment( sql, queryOptions.getComment() ); + } + if ( queryOptions.getDatabaseHints() != null && !queryOptions.getDatabaseHints().isEmpty() ) { + sql = getQueryHintString( sql, queryOptions.getDatabaseHints() ); + } + return sql; + } + + @FunctionalInterface + private interface OptionalTableUpdateStrategy { + MutationOperation buildMutationOperation( + EntityMutationTarget mutationTarget, + OptionalTableUpdate optionalTableUpdate, + SessionFactoryImplementor factory); + } + + @Override + public MutationOperation createOptionalTableUpdateOperation( + EntityMutationTarget mutationTarget, + OptionalTableUpdate optionalTableUpdate, + SessionFactoryImplementor factory) { + return optionalTableUpdateStrategy.buildMutationOperation( mutationTarget, optionalTableUpdate, factory ); + } + + private static MutationOperation usingMerge( + EntityMutationTarget mutationTarget, + OptionalTableUpdate optionalTableUpdate, + SessionFactoryImplementor factory) { + final GaussDBSqlAstTranslator translator = new GaussDBSqlAstTranslator<>( factory, optionalTableUpdate ); + return translator.createMergeOperation( optionalTableUpdate ); + } + + private static MutationOperation withoutMerge( + EntityMutationTarget mutationTarget, + OptionalTableUpdate optionalTableUpdate, + SessionFactoryImplementor factory) { + return new OptionalTableUpdateOperation( mutationTarget, optionalTableUpdate, factory ); + } + + private static class NativeParameterMarkers implements ParameterMarkerStrategy { + /** + * Singleton access + */ + public static final NativeParameterMarkers INSTANCE = new NativeParameterMarkers(); + + @Override + public String createMarker(int position, JdbcType jdbcType) { + return "$" + position; + } + } + + @Override + public int getDefaultIntervalSecondScale() { + // The maximum scale for `interval second` is 6 unfortunately + return 6; + } + + @Override + public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() { + return DmlTargetColumnQualifierSupport.TABLE_ALIAS; + } + + @Override + public boolean supportsFromClauseInUpdate() { + return true; + } + + @Override + public boolean supportsBindingNullSqlTypeForSetNull() { + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBEnumJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBEnumJdbcType.java new file mode 100644 index 000000000000..3a1d399826b4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBEnumJdbcType.java @@ -0,0 +1,168 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import org.hibernate.boot.model.relational.Database; +import org.hibernate.boot.model.relational.NamedAuxiliaryDatabaseObject; +import org.hibernate.engine.jdbc.Size; +import org.hibernate.type.descriptor.ValueBinder; +import org.hibernate.type.descriptor.ValueExtractor; +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; +import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.jdbc.BasicBinder; +import org.hibernate.type.descriptor.jdbc.BasicExtractor; +import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; +import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.Arrays; + +import static java.util.Collections.emptySet; +import static org.hibernate.type.SqlTypes.NAMED_ENUM; +import static org.hibernate.type.SqlTypes.OTHER; +import static org.hibernate.type.descriptor.converter.internal.EnumHelper.getEnumeratedValues; + +/** + * Represents a named {@code enum} type on GaussDB. + *

+ * Hibernate does not automatically use this for enums + * mapped as {@link jakarta.persistence.EnumType#STRING}, and + * instead this type must be explicitly requested using: + *

+ * @JdbcTypeCode(SqlTypes.NAMED_ENUM)
+ * 
+ * + * @see org.hibernate.type.SqlTypes#NAMED_ENUM + * @see GaussDBDialect#getEnumTypeDeclaration(String, String[]) + * @see GaussDBDialect#getCreateEnumTypeCommand(String, String[]) + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLEnumJdbcType. + */ +public class GaussDBEnumJdbcType implements JdbcType { + + public static final GaussDBEnumJdbcType INSTANCE = new GaussDBEnumJdbcType(); + + @Override + public int getJdbcTypeCode() { + return OTHER; + } + + @Override + public int getDefaultSqlTypeCode() { + return NAMED_ENUM; + } + + @Override + public JdbcLiteralFormatter getJdbcLiteralFormatter(JavaType javaType) { + @SuppressWarnings("unchecked") + final Class> enumClass = (Class>) javaType.getJavaType(); + return (appender, value, dialect, wrapperOptions) -> { + appender.appendSql( "'" ); + appender.appendSql( ((Enum) value).name() ); + appender.appendSql( "'::" ); + appender.appendSql( dialect.getEnumTypeDeclaration( enumClass ) ); + }; + } + + @Override + public String getFriendlyName() { + return "ENUM"; + } + + @Override + public String toString() { + return "EnumTypeDescriptor"; + } + + @Override + public ValueBinder getBinder(JavaType javaType) { + return new BasicBinder<>( javaType, this ) { + @Override + protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException { + st.setNull( index, Types.OTHER ); + } + + @Override + protected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException { + st.setNull( name, Types.OTHER ); + } + + @Override + protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) + throws SQLException { + st.setObject( index, getJavaType().unwrap( value, String.class, options ), Types.OTHER ); + } + + @Override + protected void doBind(CallableStatement st, X value, String name, WrapperOptions options) + throws SQLException { + st.setObject( name, getJavaType().unwrap( value, String.class, options ), Types.OTHER ); + } + }; + } + + @Override + public ValueExtractor getExtractor(JavaType javaType) { + return new BasicExtractor<>( javaType, this ) { + @Override + protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException { + return getJavaType().wrap( rs.getObject( paramIndex ), options ); + } + + @Override + protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException { + return getJavaType().wrap( statement.getObject( index ), options ); + } + + @Override + protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException { + return getJavaType().wrap( statement.getObject( name ), options ); + } + }; + } + + @Override + public void addAuxiliaryDatabaseObjects( + JavaType javaType, + BasicValueConverter valueConverter, + Size columnSize, + Database database, + JdbcTypeIndicators context) { + @SuppressWarnings("unchecked") + final Class> enumClass = (Class>) javaType.getJavaType(); + @SuppressWarnings("unchecked") + final String[] enumeratedValues = + valueConverter == null + ? getEnumeratedValues( enumClass ) + : getEnumeratedValues( enumClass, (BasicValueConverter,?>) valueConverter ) ; + if ( getDefaultSqlTypeCode() == NAMED_ENUM ) { + Arrays.sort( enumeratedValues ); + } + final Dialect dialect = database.getDialect(); + final String[] create = + dialect.getCreateEnumTypeCommand( javaType.getJavaTypeClass().getSimpleName(), enumeratedValues ); + final String[] drop = dialect.getDropEnumTypeCommand( enumClass ); + if ( create != null && create.length > 0 ) { + database.addAuxiliaryDatabaseObject( + new NamedAuxiliaryDatabaseObject( + enumClass.getSimpleName(), + database.getDefaultNamespace(), + create, + drop, + emptySet(), + true + ) + ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBOrdinalEnumJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBOrdinalEnumJdbcType.java new file mode 100644 index 000000000000..e889105ebb6b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBOrdinalEnumJdbcType.java @@ -0,0 +1,37 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import jakarta.persistence.EnumType; + +import static org.hibernate.type.SqlTypes.NAMED_ORDINAL_ENUM; + +/** + * Represents a named {@code enum} type on GaussDB. + *

+ * Hibernate does not automatically use this for enums + * mapped as {@link EnumType#ORDINAL}, and + * instead this type must be explicitly requested using: + *

+ * @JdbcTypeCode(SqlTypes.NAMED_ORDINAL_ENUM)
+ * 
+ * + * @see org.hibernate.type.SqlTypes#NAMED_ORDINAL_ENUM + * @see GaussDBDialect#getEnumTypeDeclaration(String, String[]) + * @see GaussDBDialect#getCreateEnumTypeCommand(String, String[]) + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLOrdinalEnumJdbcType. + */ +public class GaussDBOrdinalEnumJdbcType extends GaussDBEnumJdbcType { + + public static final GaussDBOrdinalEnumJdbcType INSTANCE = new GaussDBOrdinalEnumJdbcType(); + + @Override + public int getDefaultSqlTypeCode() { + return NAMED_ORDINAL_ENUM; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBSqlAstTranslator.java new file mode 100644 index 000000000000..277a65a2fe6a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBSqlAstTranslator.java @@ -0,0 +1,303 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.metamodel.mapping.JdbcMappingContainer; +import org.hibernate.query.sqm.ComparisonOperator; +import org.hibernate.query.common.FetchClauseType; +import org.hibernate.sql.ast.Clause; +import org.hibernate.sql.ast.spi.SqlAstTranslatorWithMerge; +import org.hibernate.sql.ast.tree.Statement; +import org.hibernate.sql.ast.tree.cte.CteMaterialization; +import org.hibernate.sql.ast.tree.cte.CteStatement; +import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.Literal; +import org.hibernate.sql.ast.tree.expression.Summarization; +import org.hibernate.sql.ast.tree.from.NamedTableReference; +import org.hibernate.sql.ast.tree.from.TableReference; +import org.hibernate.sql.ast.tree.insert.ConflictClause; +import org.hibernate.sql.ast.tree.insert.InsertSelectStatement; +import org.hibernate.sql.ast.tree.predicate.BooleanExpressionPredicate; +import org.hibernate.sql.ast.tree.predicate.InArrayPredicate; +import org.hibernate.sql.ast.tree.predicate.LikePredicate; +import org.hibernate.sql.ast.tree.predicate.NullnessPredicate; +import org.hibernate.sql.ast.tree.select.QueryGroup; +import org.hibernate.sql.ast.tree.select.QueryPart; +import org.hibernate.sql.ast.tree.select.QuerySpec; +import org.hibernate.sql.ast.tree.update.UpdateStatement; +import org.hibernate.sql.exec.internal.JdbcOperationQueryInsertImpl; +import org.hibernate.sql.exec.spi.JdbcOperation; +import org.hibernate.sql.exec.spi.JdbcOperationQueryInsert; +import org.hibernate.sql.model.internal.TableInsertStandard; +import org.hibernate.type.SqlTypes; + +/** + * A SQL AST translator for GaussDB. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLSqlAstTranslator. + */ +public class GaussDBSqlAstTranslator extends SqlAstTranslatorWithMerge { + + public GaussDBSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) { + super( sessionFactory, statement ); + } + + @Override + public void visitInArrayPredicate(InArrayPredicate inArrayPredicate) { + inArrayPredicate.getTestExpression().accept( this ); + appendSql( " = any (" ); + inArrayPredicate.getArrayParameter().accept( this ); + appendSql( ")" ); + } + + @Override + protected String getArrayContainsFunction() { + return super.getArrayContainsFunction(); + } + + @Override + protected void renderInsertIntoNoColumns(TableInsertStandard tableInsert) { + renderIntoIntoAndTable( tableInsert ); + appendSql( "default values" ); + } + + @Override + protected JdbcOperationQueryInsert translateInsert(InsertSelectStatement sqlAst) { + visitInsertStatement( sqlAst ); + + return new JdbcOperationQueryInsertImpl( + getSql(), + getParameterBinders(), + getAffectedTableNames(), + null + ); + } + + @Override + protected void renderTableReferenceIdentificationVariable(TableReference tableReference) { + final String identificationVariable = tableReference.getIdentificationVariable(); + if ( identificationVariable != null ) { + final Clause currentClause = getClauseStack().getCurrent(); + if ( currentClause == Clause.INSERT ) { + // GaussDB requires the "as" keyword for inserts + appendSql( " as " ); + } + else { + append( WHITESPACE ); + } + append( tableReference.getIdentificationVariable() ); + } + } + + @Override + protected void renderDmlTargetTableExpression(NamedTableReference tableReference) { + super.renderDmlTargetTableExpression( tableReference ); + final Statement currentStatement = getStatementStack().getCurrent(); + if ( !( currentStatement instanceof UpdateStatement updateStatement ) + || !hasNonTrivialFromClause( updateStatement.getFromClause() ) ) { + // For UPDATE statements we render a full FROM clause and a join condition to match target table rows, + // but for that to work, we have to omit the alias for the target table reference here + renderTableReferenceIdentificationVariable( tableReference ); + } + } + + @Override + protected void renderFromClauseAfterUpdateSet(UpdateStatement statement) { + renderFromClauseJoiningDmlTargetReference( statement ); + } + + @Override + protected void visitConflictClause(ConflictClause conflictClause) { + visitStandardConflictClause( conflictClause ); + } + + @Override + protected void renderExpressionAsClauseItem(Expression expression) { + expression.accept( this ); + } + + @Override + protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) { + final JdbcMappingContainer lhsExpressionType = lhs.getExpressionType(); + if ( lhsExpressionType != null && lhsExpressionType.getJdbcTypeCount() == 1 + && lhsExpressionType.getSingleJdbcMapping().getJdbcType().getDdlTypeCode() == SqlTypes.SQLXML ) { + // In GaussDB, XMLTYPE is not "comparable", so we have to cast the two parts to varchar for this purpose + switch ( operator ) { + case EQUAL: + case NOT_DISTINCT_FROM: + case NOT_EQUAL: + case DISTINCT_FROM: + appendSql( "cast(" ); + lhs.accept( this ); + appendSql( " as text)" ); + appendSql( operator.sqlText() ); + appendSql( "cast(" ); + rhs.accept( this ); + appendSql( " as text)" ); + return; + default: + // Fall through + break; + } + } + renderComparisonStandard( lhs, operator, rhs ); + } + + @Override + public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) { + final boolean isNegated = booleanExpressionPredicate.isNegated(); + if ( isNegated ) { + appendSql( "not(" ); + } + booleanExpressionPredicate.getExpression().accept( this ); + if ( isNegated ) { + appendSql( CLOSE_PARENTHESIS ); + } + } + + @Override + public void visitNullnessPredicate(NullnessPredicate nullnessPredicate) { + final Expression expression = nullnessPredicate.getExpression(); + final JdbcMappingContainer expressionType = expression.getExpressionType(); + if ( isStruct( expressionType ) ) { + // Surprise, the null predicate checks if all components of the struct are null or not, + // rather than the column itself, so we have to use the distinct from predicate to implement this instead + expression.accept( this ); + if ( nullnessPredicate.isNegated() ) { + appendSql( " is distinct from null" ); + } + else { + appendSql( " is not distinct from null" ); + } + } + else { + super.visitNullnessPredicate( nullnessPredicate ); + } + } + + @Override + protected void renderMaterializationHint(CteMaterialization materialization) { + if ( materialization == CteMaterialization.NOT_MATERIALIZED ) { + appendSql( "not " ); + } + appendSql( "materialized " ); + } + + @Override + protected String getForUpdate() { + return getDialect().getForUpdateString(); + } + + @Override + protected String getForShare(int timeoutMillis) { + // Note that `for key share` is inappropriate as that only means "prevent PK changes" + return " for share"; + } + + protected boolean shouldEmulateFetchClause(QueryPart queryPart) { + // Check if current query part is already row numbering to avoid infinite recursion + if ( getQueryPartForRowNumbering() == queryPart || isRowsOnlyFetchClauseType( queryPart ) ) { + return false; + } + return !getDialect().supportsFetchClause( queryPart.getFetchClauseType() ); + } + + @Override + public void visitQueryGroup(QueryGroup queryGroup) { + if ( shouldEmulateFetchClause( queryGroup ) ) { + emulateFetchOffsetWithWindowFunctions( queryGroup, true ); + } + else { + super.visitQueryGroup( queryGroup ); + } + } + + @Override + public void visitQuerySpec(QuerySpec querySpec) { + if ( shouldEmulateFetchClause( querySpec ) ) { + emulateFetchOffsetWithWindowFunctions( querySpec, true ); + } + else { + super.visitQuerySpec( querySpec ); + } + } + + @Override + public void visitOffsetFetchClause(QueryPart queryPart) { + if ( !isRowNumberingCurrentQueryPart() ) { + if ( getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY ) ) { + renderOffsetFetchClause( queryPart, true ); + } + else { + renderLimitOffsetClause( queryPart ); + } + } + } + + @Override + protected void renderStandardCycleClause(CteStatement cte) { + super.renderStandardCycleClause( cte ); + if ( cte.getCycleMarkColumn() != null && cte.getCyclePathColumn() == null && getDialect().supportsRecursiveCycleUsingClause() ) { + appendSql( " using " ); + appendSql( determineCyclePathColumnName( cte ) ); + } + } + + @Override + protected void renderPartitionItem(Expression expression) { + // We render an empty group instead of literals as some DBs don't support grouping by literals + // Note that integer literals, which refer to select item positions, are handled in #visitGroupByClause + if ( expression instanceof Literal ) { + appendSql( "()" ); + } + else if ( expression instanceof Summarization summarization ) { + appendSql( summarization.getKind().sqlText() ); + appendSql( OPEN_PARENTHESIS ); + renderCommaSeparated( summarization.getGroupings() ); + appendSql( CLOSE_PARENTHESIS ); + } + else { + expression.accept( this ); + } + } + + @Override + public void visitLikePredicate(LikePredicate likePredicate) { + // We need a custom implementation here because GaussDB + // uses the backslash character as default escape character + // According to the documentation, we can overcome this by specifying an empty escape character + // See https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE + likePredicate.getMatchExpression().accept( this ); + if ( likePredicate.isNegated() ) { + appendSql( " not" ); + } + if ( likePredicate.isCaseSensitive() ) { + appendSql( " like " ); + } + else { + appendSql( WHITESPACE ); + appendSql( getDialect().getCaseInsensitiveLike() ); + appendSql( WHITESPACE ); + } + likePredicate.getPattern().accept( this ); + if ( likePredicate.getEscapeCharacter() != null ) { + appendSql( " escape " ); + likePredicate.getEscapeCharacter().accept( this ); + } + } + + @Override + public void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression) { + appendSql( OPEN_PARENTHESIS ); + visitArithmeticOperand( arithmeticExpression.getLeftHandOperand() ); + appendSql( arithmeticExpression.getOperator().getOperatorSqlTextString() ); + visitArithmeticOperand( arithmeticExpression.getRightHandOperand() ); + appendSql( CLOSE_PARENTHESIS ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBStructCastingJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBStructCastingJdbcType.java new file mode 100644 index 000000000000..b2d93f7f426d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBStructCastingJdbcType.java @@ -0,0 +1,100 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.hibernate.boot.model.naming.Identifier; +import org.hibernate.metamodel.mapping.EmbeddableMappingType; +import org.hibernate.metamodel.spi.RuntimeModelCreationContext; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.type.descriptor.ValueBinder; +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; +import org.hibernate.type.descriptor.jdbc.BasicBinder; + +/** + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLStructCastingJdbcType. + */ +public class GaussDBStructCastingJdbcType extends AbstractGaussDBStructJdbcType { + + public static final GaussDBStructCastingJdbcType INSTANCE = new GaussDBStructCastingJdbcType(); + public GaussDBStructCastingJdbcType() { + this( null, null, null ); + } + + private GaussDBStructCastingJdbcType( + EmbeddableMappingType embeddableMappingType, + String typeName, + int[] orderMapping) { + super( embeddableMappingType, typeName, orderMapping ); + } + + @Override + public AggregateJdbcType resolveAggregateJdbcType( + EmbeddableMappingType mappingType, + String sqlType, + RuntimeModelCreationContext creationContext) { + return new GaussDBStructCastingJdbcType( + mappingType, + sqlType, + creationContext.getBootModel() + .getDatabase() + .getDefaultNamespace() + .locateUserDefinedType( Identifier.toIdentifier( sqlType ) ) + .getOrderMapping() + ); + } + + @Override + public void appendWriteExpression( + String writeExpression, + SqlAppender appender, + Dialect dialect) { + appender.append( "cast(" ); + appender.append( writeExpression ); + appender.append( " as " ); + appender.append( getStructTypeName() ); + appender.append( ')' ); + } + + @Override + public ValueBinder getBinder(JavaType javaType) { + return new BasicBinder<>( javaType, this ) { + @Override + protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) + throws SQLException { + final String stringValue = ( (GaussDBStructCastingJdbcType) getJdbcType() ).toString( + value, + getJavaType(), + options + ); + st.setString( index, stringValue ); + } + + @Override + protected void doBind(CallableStatement st, X value, String name, WrapperOptions options) + throws SQLException { + final String stringValue = ( (GaussDBStructCastingJdbcType) getJdbcType() ).toString( + value, + getJavaType(), + options + ); + st.setString( name, stringValue ); + } + + @Override + public Object getBindValue(X value, WrapperOptions options) throws SQLException { + return ( (GaussDBStructCastingJdbcType) getJdbcType() ).getBindValue( value, options ); + } + }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBUUIDJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBUUIDJdbcType.java new file mode 100644 index 000000000000..9c4a106aa5e4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/GaussDBUUIDJdbcType.java @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.UUID; + +import org.hibernate.type.descriptor.ValueBinder; +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.jdbc.BasicBinder; +import org.hibernate.type.descriptor.jdbc.UUIDJdbcType; + +/** + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLUUIDJdbcType. + */ +public class GaussDBUUIDJdbcType extends UUIDJdbcType { + + /** + * Singleton access + */ + public static final GaussDBUUIDJdbcType INSTANCE = new GaussDBUUIDJdbcType(); + + @Override + public ValueBinder getBinder(JavaType javaType) { + return new BasicBinder<>( javaType, this ) { + @Override + protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException { + st.setNull( index, getJdbcType().getJdbcTypeCode(), "uuid" ); + } + + @Override + protected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException { + st.setNull( name, getJdbcType().getJdbcTypeCode(), "uuid" ); + } + + @Override + protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) + throws SQLException { + st.setObject( index, getJavaType().unwrap( value, UUID.class, options ) ); + } + + @Override + protected void doBind(CallableStatement st, X value, String name, WrapperOptions options) + throws SQLException { + st.setObject( name, getJavaType().unwrap( value, UUID.class, options ) ); + } + }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/aggregate/GaussDBAggregateSupport.java b/hibernate-core/src/main/java/org/hibernate/dialect/aggregate/GaussDBAggregateSupport.java new file mode 100644 index 000000000000..90d300f481fe --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/aggregate/GaussDBAggregateSupport.java @@ -0,0 +1,630 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.aggregate; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.hibernate.dialect.Dialect; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.mapping.Column; +import org.hibernate.metamodel.mapping.EmbeddableMappingType; +import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.metamodel.mapping.SelectableMapping; +import org.hibernate.metamodel.mapping.SelectablePath; +import org.hibernate.metamodel.mapping.SqlTypedMapping; +import org.hibernate.sql.ast.SqlAstNodeRenderingMode; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.type.BasicPluralType; +import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; +import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.descriptor.jdbc.XmlHelper; +import org.hibernate.type.spi.TypeConfiguration; + +import static org.hibernate.type.SqlTypes.ARRAY; +import static org.hibernate.type.SqlTypes.BIGINT; +import static org.hibernate.type.SqlTypes.BINARY; +import static org.hibernate.type.SqlTypes.BOOLEAN; +import static org.hibernate.type.SqlTypes.DOUBLE; +import static org.hibernate.type.SqlTypes.FLOAT; +import static org.hibernate.type.SqlTypes.INTEGER; +import static org.hibernate.type.SqlTypes.JSON; +import static org.hibernate.type.SqlTypes.JSON_ARRAY; +import static org.hibernate.type.SqlTypes.LONG32VARBINARY; +import static org.hibernate.type.SqlTypes.SMALLINT; +import static org.hibernate.type.SqlTypes.SQLXML; +import static org.hibernate.type.SqlTypes.STRUCT; +import static org.hibernate.type.SqlTypes.STRUCT_ARRAY; +import static org.hibernate.type.SqlTypes.STRUCT_TABLE; +import static org.hibernate.type.SqlTypes.TINYINT; +import static org.hibernate.type.SqlTypes.VARBINARY; +import static org.hibernate.type.SqlTypes.XML_ARRAY; + +/** + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLAggregateSupport. + */ +public class GaussDBAggregateSupport extends AggregateSupportImpl { + + private static final AggregateSupport INSTANCE = new GaussDBAggregateSupport(); + + private static final String XML_EXTRACT_START = "xmlelement(name \"" + XmlHelper.ROOT_TAG + "\",(select xmlagg(t.v) from xmltable("; + private static final String XML_EXTRACT_SEPARATOR = "/*' passing "; + private static final String XML_EXTRACT_END = " columns v xml path '.')t))"; + private static final String XML_QUERY_START = "(select xmlagg(t.v) from xmltable("; + private static final String XML_QUERY_SEPARATOR = "' passing "; + private static final String XML_QUERY_END = " columns v xml path '.')t)"; + + public static AggregateSupport valueOf(Dialect dialect) { + return GaussDBAggregateSupport.INSTANCE; + } + + @Override + public String aggregateComponentCustomReadExpression( + String template, + String placeholder, + String aggregateParentReadExpression, + String columnExpression, + int aggregateColumnTypeCode, + SqlTypedMapping column, + TypeConfiguration typeConfiguration) { + switch ( aggregateColumnTypeCode ) { + case JSON_ARRAY: + case JSON: + switch ( column.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode() ) { + case JSON: + case JSON_ARRAY: + return template.replace( + placeholder, + aggregateParentReadExpression + "->'" + columnExpression + "'" + ); + case BINARY: + case VARBINARY: + case LONG32VARBINARY: + // We encode binary data as hex, so we have to decode here + return template.replace( + placeholder, + "decode(" + aggregateParentReadExpression + "->>'" + columnExpression + "','hex')" + ); + case ARRAY: + final BasicPluralType pluralType = (BasicPluralType) column.getJdbcMapping(); + switch ( pluralType.getElementType().getJdbcType().getDefaultSqlTypeCode() ) { + case BOOLEAN: + case TINYINT: + case SMALLINT: + case INTEGER: + case BIGINT: + case FLOAT: + case DOUBLE: + // For types that are natively supported in jsonb we can use jsonb_array_elements, + // but note that we can't use that for string types, + // because casting a jsonb[] to text[] will not omit the quotes of the jsonb text values + return template.replace( + placeholder, + "cast(array(select jsonb_array_elements(" + aggregateParentReadExpression + "->'" + columnExpression + "')) as " + column.getColumnDefinition() + ')' + ); + case BINARY: + case VARBINARY: + case LONG32VARBINARY: + // We encode binary data as hex, so we have to decode here + return template.replace( + placeholder, + "array(select decode(jsonb_array_elements_text(" + aggregateParentReadExpression + "->'" + columnExpression + "'),'hex'))" + ); + default: + return template.replace( + placeholder, + "cast(array(select jsonb_array_elements_text(" + aggregateParentReadExpression + "->'" + columnExpression + "')) as " + column.getColumnDefinition() + ')' + ); + } + default: + return template.replace( + placeholder, + "cast(" + aggregateParentReadExpression + "->>'" + columnExpression + "' as " + column.getColumnDefinition() + ')' + ); + } + case XML_ARRAY: + case SQLXML: + switch ( column.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode() ) { + case SQLXML: + return template.replace( + placeholder, + XML_EXTRACT_START + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/*" ) + XML_EXTRACT_END + ); + case XML_ARRAY: + if ( typeConfiguration.getCurrentBaseSqlTypeIndicators().isXmlFormatMapperLegacyFormatEnabled() ) { + throw new IllegalArgumentException( "XML array '" + columnExpression + "' in '" + aggregateParentReadExpression + "' is not supported with legacy format enabled." ); + } + else { + return template.replace( + placeholder, + "xmlelement(name \"Collection\",(select xmlagg(t.v order by t.i) from xmltable(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/*" ) + " columns v xml path '.', i for ordinality)t))" + ); + } + case BINARY: + case VARBINARY: + case LONG32VARBINARY: + // We encode binary data as hex, so we have to decode here + return template.replace( + placeholder, + "decode((select t.v from xmltable(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression )+ " columns v text path '.') t),'hex')" + ); + case ARRAY: + throw new UnsupportedOperationException( "Transforming XML_ARRAY to native arrays is not supported on GaussDB!" ); + default: + return template.replace( + placeholder, + "(select t.v from xmltable(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression ) + " columns v " + column.getColumnDefinition() + " path '.') t)" + ); + } + case STRUCT: + case STRUCT_ARRAY: + case STRUCT_TABLE: + return template.replace( placeholder, '(' + aggregateParentReadExpression + ")." + columnExpression ); + } + throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateColumnTypeCode ); + } + + private static String xmlExtractArguments(String aggregateParentReadExpression, String xpathFragment) { + final String extractArguments; + int separatorIndex; + if ( aggregateParentReadExpression.startsWith( XML_EXTRACT_START ) + && aggregateParentReadExpression.endsWith( XML_EXTRACT_END ) + && (separatorIndex = aggregateParentReadExpression.indexOf( XML_EXTRACT_SEPARATOR )) != -1 ) { + final StringBuilder sb = new StringBuilder( aggregateParentReadExpression.length() - XML_EXTRACT_START.length() + xpathFragment.length() ); + sb.append( aggregateParentReadExpression, XML_EXTRACT_START.length(), separatorIndex ); + sb.append( '/' ); + sb.append( xpathFragment ); + sb.append( aggregateParentReadExpression, separatorIndex + 2, aggregateParentReadExpression.length() - XML_EXTRACT_END.length() ); + extractArguments = sb.toString(); + } + else if ( aggregateParentReadExpression.startsWith( XML_QUERY_START ) + && aggregateParentReadExpression.endsWith( XML_QUERY_END ) + && (separatorIndex = aggregateParentReadExpression.indexOf( XML_QUERY_SEPARATOR )) != -1 ) { + final StringBuilder sb = new StringBuilder( aggregateParentReadExpression.length() - XML_QUERY_START.length() + xpathFragment.length() ); + sb.append( aggregateParentReadExpression, XML_QUERY_START.length(), separatorIndex ); + sb.append( '/' ); + sb.append( xpathFragment ); + sb.append( aggregateParentReadExpression, separatorIndex, aggregateParentReadExpression.length() - XML_QUERY_END.length() ); + extractArguments = sb.toString(); + } + else { + extractArguments = "'/" + XmlHelper.ROOT_TAG + "/" + xpathFragment + "' passing " + aggregateParentReadExpression; + } + return extractArguments; + } + + private static String jsonCustomWriteExpression(String customWriteExpression, JdbcMapping jdbcMapping) { + final int sqlTypeCode = jdbcMapping.getJdbcType().getDefaultSqlTypeCode(); + switch ( sqlTypeCode ) { + case BINARY: + case VARBINARY: + case LONG32VARBINARY: + // We encode binary data as hex + return "to_jsonb(encode(" + customWriteExpression + ",'hex'))"; + case ARRAY: + final BasicPluralType pluralType = (BasicPluralType) jdbcMapping; + switch ( pluralType.getElementType().getJdbcType().getDefaultSqlTypeCode() ) { + case BINARY: + case VARBINARY: + case LONG32VARBINARY: + // We encode binary data as hex + return "to_jsonb(array(select encode(unnest(" + customWriteExpression + "),'hex')))"; + default: + return "to_jsonb(" + customWriteExpression + ")"; + } + default: + return "to_jsonb(" + customWriteExpression + ")"; + } + } + + private static String xmlCustomWriteExpression(String customWriteExpression, JdbcMapping jdbcMapping) { + final int sqlTypeCode = jdbcMapping.getJdbcType().getDefaultSqlTypeCode(); + switch ( sqlTypeCode ) { + case BINARY: + case VARBINARY: + case LONG32VARBINARY: + // We encode binary data as hex + return "encode(" + customWriteExpression + ",'hex')"; +// case ARRAY: +// final BasicPluralType pluralType = (BasicPluralType) jdbcMapping; +// switch ( pluralType.getElementType().getJdbcType().getDefaultSqlTypeCode() ) { +// case BINARY: +// case VARBINARY: +// case LONG32VARBINARY: +// // We encode binary data as hex +// return "to_jsonb(array(select encode(unnest(" + customWriteExpression + "),'hex')))"; +// default: +// return "to_jsonb(" + customWriteExpression + ")"; +// } + default: + return customWriteExpression; + } + } + + @Override + public String aggregateComponentAssignmentExpression( + String aggregateParentAssignmentExpression, + String columnExpression, + int aggregateColumnTypeCode, + Column column) { + switch ( aggregateColumnTypeCode ) { + case JSON: + case JSON_ARRAY: + case SQLXML: + case XML_ARRAY: + // For JSON/XML we always have to replace the whole object + return aggregateParentAssignmentExpression; + case STRUCT: + case STRUCT_ARRAY: + case STRUCT_TABLE: + return aggregateParentAssignmentExpression + "." + columnExpression; + } + throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateColumnTypeCode ); + } + + @Override + public boolean requiresAggregateCustomWriteExpressionRenderer(int aggregateSqlTypeCode) { + switch ( aggregateSqlTypeCode ) { + case JSON: + case SQLXML: + return true; + } + return false; + } + + @Override + public boolean preferSelectAggregateMapping(int aggregateSqlTypeCode) { + // The JDBC driver does not support selecting java.sql.Struct, so return false to select individual parts + return aggregateSqlTypeCode != STRUCT; + } + + @Override + public WriteExpressionRenderer aggregateCustomWriteExpressionRenderer( + SelectableMapping aggregateColumn, + SelectableMapping[] columnsToUpdate, + TypeConfiguration typeConfiguration) { + final int aggregateSqlTypeCode = aggregateColumn.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode(); + switch ( aggregateSqlTypeCode ) { + case JSON: + return new RootJsonWriteExpression( aggregateColumn, columnsToUpdate ); + case SQLXML: + return new RootXmlWriteExpression( aggregateColumn, columnsToUpdate ); + } + throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateSqlTypeCode ); + } + + interface JsonWriteExpression { + void append( + SqlAppender sb, + String path, + SqlAstTranslator translator, + AggregateColumnWriteExpression expression); + } + private static class AggregateJsonWriteExpression implements JsonWriteExpression { + private final LinkedHashMap subExpressions = new LinkedHashMap<>(); + + protected void initializeSubExpressions(SelectableMapping[] columns) { + for ( SelectableMapping column : columns ) { + final SelectablePath selectablePath = column.getSelectablePath(); + final SelectablePath[] parts = selectablePath.getParts(); + AggregateJsonWriteExpression currentAggregate = this; + for ( int i = 1; i < parts.length - 1; i++ ) { + currentAggregate = (AggregateJsonWriteExpression) currentAggregate.subExpressions.computeIfAbsent( + parts[i].getSelectableName(), + k -> new AggregateJsonWriteExpression() + ); + } + final String customWriteExpression = column.getWriteExpression(); + currentAggregate.subExpressions.put( + parts[parts.length - 1].getSelectableName(), + new BasicJsonWriteExpression( + column, + jsonCustomWriteExpression( customWriteExpression, column.getJdbcMapping() ) + ) + ); + } + } + + @Override + public void append( + SqlAppender sb, + String path, + SqlAstTranslator translator, + AggregateColumnWriteExpression expression) { + sb.append( "||jsonb_build_object" ); + char separator = '('; + for ( Map.Entry entry : subExpressions.entrySet() ) { + final String column = entry.getKey(); + final JsonWriteExpression value = entry.getValue(); + final String subPath = path + "->'" + column + "'"; + sb.append( separator ); + if ( value instanceof AggregateJsonWriteExpression ) { + sb.append( '\'' ); + sb.append( column ); + sb.append( "',coalesce(" ); + sb.append( subPath ); + sb.append( ",'{}')" ); + value.append( sb, subPath, translator, expression ); + } + else { + value.append( sb, subPath, translator, expression ); + } + separator = ','; + } + sb.append( ')' ); + } + } + + private static class RootJsonWriteExpression extends AggregateJsonWriteExpression + implements WriteExpressionRenderer { + private final boolean nullable; + private final String path; + + RootJsonWriteExpression(SelectableMapping aggregateColumn, SelectableMapping[] columns) { + this.nullable = aggregateColumn.isNullable(); + this.path = aggregateColumn.getSelectionExpression(); + initializeSubExpressions( columns ); + } + + @Override + public void render( + SqlAppender sqlAppender, + SqlAstTranslator translator, + AggregateColumnWriteExpression aggregateColumnWriteExpression, + String qualifier) { + final String basePath; + if ( qualifier == null || qualifier.isBlank() ) { + basePath = path; + } + else { + basePath = qualifier + "." + path; + } + if ( nullable ) { + sqlAppender.append( "coalesce(" ); + sqlAppender.append( basePath ); + sqlAppender.append( ",'{}')" ); + } + else { + sqlAppender.append( basePath ); + } + append( sqlAppender, basePath, translator, aggregateColumnWriteExpression ); + } + } + private static class BasicJsonWriteExpression implements JsonWriteExpression { + + private final SelectableMapping selectableMapping; + private final String customWriteExpressionStart; + private final String customWriteExpressionEnd; + + BasicJsonWriteExpression(SelectableMapping selectableMapping, String customWriteExpression) { + this.selectableMapping = selectableMapping; + if ( customWriteExpression.equals( "?" ) ) { + this.customWriteExpressionStart = ""; + this.customWriteExpressionEnd = ""; + } + else { + final String[] parts = StringHelper.split( "?", customWriteExpression ); + assert parts.length == 2; + this.customWriteExpressionStart = parts[0]; + this.customWriteExpressionEnd = parts[1]; + } + } + + @Override + public void append( + SqlAppender sb, + String path, + SqlAstTranslator translator, + AggregateColumnWriteExpression expression) { + sb.append( '\'' ); + sb.append( selectableMapping.getSelectableName() ); + sb.append( "'," ); + sb.append( customWriteExpressionStart ); + // We use NO_UNTYPED here so that expressions which require type inference are casted explicitly, + // since we don't know how the custom write expression looks like where this is embedded, + // so we have to be pessimistic and avoid ambiguities + translator.render( expression.getValueExpression( selectableMapping ), SqlAstNodeRenderingMode.NO_UNTYPED ); + sb.append( customWriteExpressionEnd ); + } + } + + interface XmlWriteExpression { + void append( + SqlAppender sb, + String path, + SqlAstTranslator translator, + AggregateColumnWriteExpression expression); + } + private static class AggregateXmlWriteExpression implements XmlWriteExpression { + + private final SelectableMapping selectableMapping; + private final String columnDefinition; + private final LinkedHashMap subExpressions = new LinkedHashMap<>(); + + private AggregateXmlWriteExpression(SelectableMapping selectableMapping, String columnDefinition) { + this.selectableMapping = selectableMapping; + this.columnDefinition = columnDefinition; + } + + protected void initializeSubExpressions(SelectableMapping aggregateColumn, SelectableMapping[] columns) { + for ( SelectableMapping column : columns ) { + final SelectablePath selectablePath = column.getSelectablePath(); + final SelectablePath[] parts = selectablePath.getParts(); + AggregateXmlWriteExpression currentAggregate = this; + for ( int i = 1; i < parts.length - 1; i++ ) { + final AggregateJdbcType aggregateJdbcType = (AggregateJdbcType) currentAggregate.selectableMapping.getJdbcMapping().getJdbcType(); + final EmbeddableMappingType embeddableMappingType = aggregateJdbcType.getEmbeddableMappingType(); + final int selectableIndex = embeddableMappingType.getSelectableIndex( parts[i].getSelectableName() ); + currentAggregate = (AggregateXmlWriteExpression) currentAggregate.subExpressions.computeIfAbsent( + parts[i].getSelectableName(), + k -> new AggregateXmlWriteExpression( embeddableMappingType.getJdbcValueSelectable( selectableIndex ), columnDefinition ) + ); + } + final String customWriteExpression = column.getWriteExpression(); + currentAggregate.subExpressions.put( + parts[parts.length - 1].getSelectableName(), + new BasicXmlWriteExpression( + column, + xmlCustomWriteExpression( customWriteExpression, column.getJdbcMapping() ) + ) + ); + } + passThroughUnsetSubExpressions( aggregateColumn ); + } + + protected void passThroughUnsetSubExpressions(SelectableMapping aggregateColumn) { + final AggregateJdbcType aggregateJdbcType = (AggregateJdbcType) aggregateColumn.getJdbcMapping().getJdbcType(); + final EmbeddableMappingType embeddableMappingType = aggregateJdbcType.getEmbeddableMappingType(); + final int jdbcValueCount = embeddableMappingType.getJdbcValueCount(); + for ( int i = 0; i < jdbcValueCount; i++ ) { + final SelectableMapping selectableMapping = embeddableMappingType.getJdbcValueSelectable( i ); + + final XmlWriteExpression xmlWriteExpression = subExpressions.get( selectableMapping.getSelectableName() ); + if ( xmlWriteExpression == null ) { + subExpressions.put( + selectableMapping.getSelectableName(), + new PassThroughXmlWriteExpression( selectableMapping ) + ); + } + else if ( xmlWriteExpression instanceof AggregateXmlWriteExpression writeExpression ) { + writeExpression.passThroughUnsetSubExpressions( selectableMapping ); + } + } + } + + protected String getTagName() { + return selectableMapping.getSelectableName(); + } + + @Override + public void append( + SqlAppender sb, + String path, + SqlAstTranslator translator, + AggregateColumnWriteExpression expression) { + sb.append( "xmlelement(name " ); + sb.appendDoubleQuoteEscapedString( getTagName() ); + sb.append( ",xmlconcat" ); + char separator = '('; + for ( Map.Entry entry : subExpressions.entrySet() ) { + sb.append( separator ); + + final XmlWriteExpression value = entry.getValue(); + if ( value instanceof AggregateXmlWriteExpression ) { + final String subPath = XML_QUERY_START + xmlExtractArguments( path, entry.getKey() ) + XML_QUERY_END; + value.append( sb, subPath, translator, expression ); + } + else { + value.append( sb, path, translator, expression ); + } + separator = ','; + } + sb.append( "))" ); + } + } + + private static class RootXmlWriteExpression extends AggregateXmlWriteExpression + implements WriteExpressionRenderer { + private final String path; + + RootXmlWriteExpression(SelectableMapping aggregateColumn, SelectableMapping[] columns) { + super( aggregateColumn, aggregateColumn.getColumnDefinition() ); + path = aggregateColumn.getSelectionExpression(); + initializeSubExpressions( aggregateColumn, columns ); + } + + @Override + protected String getTagName() { + return XmlHelper.ROOT_TAG; + } + + @Override + public void render( + SqlAppender sqlAppender, + SqlAstTranslator translator, + AggregateColumnWriteExpression aggregateColumnWriteExpression, + String qualifier) { + final String basePath; + if ( qualifier == null || qualifier.isBlank() ) { + basePath = path; + } + else { + basePath = qualifier + "." + path; + } + append( sqlAppender, XML_QUERY_START + "'/" + getTagName() + "' passing " + basePath + XML_QUERY_END, translator, aggregateColumnWriteExpression ); + } + } + private static class BasicXmlWriteExpression implements XmlWriteExpression { + + private final SelectableMapping selectableMapping; + private final String[] customWriteExpressionParts; + + BasicXmlWriteExpression(SelectableMapping selectableMapping, String customWriteExpression) { + this.selectableMapping = selectableMapping; + if ( customWriteExpression.equals( "?" ) ) { + this.customWriteExpressionParts = new String[]{ "", "" }; + } + else { + assert !customWriteExpression.startsWith( "?" ); + final String[] parts = StringHelper.split( "?", customWriteExpression ); + assert parts.length == 2 || (parts.length & 1) == 1; + this.customWriteExpressionParts = parts; + } + } + + @Override + public void append( + SqlAppender sb, + String path, + SqlAstTranslator translator, + AggregateColumnWriteExpression expression) { + final JdbcType jdbcType = selectableMapping.getJdbcMapping().getJdbcType(); + final boolean isArray = jdbcType.getDefaultSqlTypeCode() == XML_ARRAY; + sb.append( "xmlelement(name " ); + sb.appendDoubleQuoteEscapedString( selectableMapping.getSelectableName() ); + sb.append( ',' ); + if ( isArray ) { + // Remove the tag to wrap the value into the selectable specific tag + sb.append( "(select xmlagg(t.v order by t.i) from xmltable('/Collection/*' passing " ); + } + sb.append( customWriteExpressionParts[0] ); + for ( int i = 1; i < customWriteExpressionParts.length; i++ ) { + // We use NO_UNTYPED here so that expressions which require type inference are casted explicitly, + // since we don't know how the custom write expression looks like where this is embedded, + // so we have to be pessimistic and avoid ambiguities + translator.render( expression.getValueExpression( selectableMapping ), SqlAstNodeRenderingMode.NO_UNTYPED ); + sb.append( customWriteExpressionParts[i] ); + } + if ( isArray ) { + sb.append( " columns v xml path '.', i for ordinality)t)" ); + } + sb.append( ')' ); + } + } + + private static class PassThroughXmlWriteExpression implements XmlWriteExpression { + + private final SelectableMapping selectableMapping; + + PassThroughXmlWriteExpression(SelectableMapping selectableMapping) { + this.selectableMapping = selectableMapping; + } + + @Override + public void append( + SqlAppender sb, + String path, + SqlAstTranslator translator, + AggregateColumnWriteExpression expression) { + sb.append( XML_QUERY_START ); + sb.append( xmlExtractArguments( path, selectableMapping.getSelectableName() ) ); + sb.append( XML_QUERY_END ); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java index 5dfe7936ab3f..7f7a095cd659 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java @@ -14,6 +14,7 @@ import org.hibernate.dialect.function.array.*; import org.hibernate.dialect.function.json.*; import org.hibernate.dialect.function.xml.DB2XmlTableFunction; +import org.hibernate.dialect.function.xml.GaussDBXmlQueryFunction; import org.hibernate.dialect.function.xml.H2XmlConcatFunction; import org.hibernate.dialect.function.xml.H2XmlElementFunction; import org.hibernate.dialect.function.xml.H2XmlForestFunction; @@ -1468,7 +1469,7 @@ public void localtimeLocaltimestamp() { .setUseParenthesesWhenNoArgs( false ) .register(); functionRegistry.noArgsBuilder( "local_datetime", "localtimestamp" ) - .setInvariantType( basicTypeRegistry.resolve( StandardBasicTypes.LOCAL_DATE_TIME ) ) + .setInvariantType ( basicTypeRegistry.resolve( StandardBasicTypes.LOCAL_DATE_TIME ) ) .setUseParenthesesWhenNoArgs( false ) .register(); } @@ -2572,6 +2573,15 @@ public void format_toChar() { functionRegistry.register( "format", new FormatFunction( "to_char", typeConfiguration ) ); } + /** + * Usually Oracle-style (except for Informix which quite close to MySQL-style) + * + * @see org.hibernate.dialect.OracleDialect#datetimeFormat + */ + public void format_toChar_gauss() { + functionRegistry.register( "format", new GaussDBFormatFunction( "to_char", typeConfiguration ) ); + } + /** * MySQL-style (also Ingres) * @@ -2662,6 +2672,14 @@ public void array_postgresql() { functionRegistry.register( "array_list", new PostgreSQLArrayConstructorFunction( true ) ); } + /** + * GaussDB array() constructor function + */ + public void array_gaussdb() { + functionRegistry.register( "array", new GaussDBArrayConstructorFunction( false ) ); + functionRegistry.register( "array_list", new GaussDBArrayConstructorFunction( true ) ); + } + /** * Google Spanner array() constructor function */ @@ -2746,6 +2764,16 @@ public void arrayContains_postgresql() { functionRegistry.register( "array_includes_nullable", new ArrayIncludesOperatorFunction( true, typeConfiguration ) ); } + /** + * GaussDB array contains operator + */ + public void arrayContains_gaussdb() { + functionRegistry.register( "array_contains", new GaussDBArrayContainsOperatorFunction( false, typeConfiguration ) ); + functionRegistry.register( "array_contains_nullable", new GaussDBArrayContainsOperatorFunction( true, typeConfiguration ) ); + functionRegistry.register( "array_includes", new ArrayIncludesOperatorFunction( false, typeConfiguration ) ); + functionRegistry.register( "array_includes_nullable", new ArrayIncludesOperatorFunction( true, typeConfiguration ) ); + } + /** * Oracle array_contains() function */ @@ -2798,6 +2826,16 @@ public void arrayIntersects_postgresql() { functionRegistry.registerAlternateKey( "array_overlaps_nullable", "array_intersects_nullable" ); } + /** + * GaussDB array intersects operator + */ + public void arrayIntersects_gaussdb() { + functionRegistry.register( "array_intersects", new ArrayIntersectsOperatorFunction( false, typeConfiguration ) ); + functionRegistry.register( "array_intersects_nullable", new ArrayIntersectsOperatorFunction( true, typeConfiguration ) ); + functionRegistry.registerAlternateKey( "array_overlaps", "array_intersects" ); + functionRegistry.registerAlternateKey( "array_overlaps_nullable", "array_intersects_nullable" ); + } + /** * Oracle array_intersects() function */ @@ -2821,6 +2859,13 @@ public void arrayPosition_postgresql() { functionRegistry.register( "array_position", new PostgreSQLArrayPositionFunction( typeConfiguration ) ); } + /** + * GaussDB array_position() function + */ + public void arrayPosition_gaussdb() { + functionRegistry.register( "array_position", new GaussDBArrayPositionFunction( typeConfiguration ) ); + } + /** * H2 array_position() function */ @@ -2937,6 +2982,13 @@ public void arrayConcat_postgresql() { functionRegistry.register( "array_concat", new PostgreSQLArrayConcatFunction() ); } + /** + * PostgreSQL array_concat() function + */ + public void arrayConcat_gaussdb() { + functionRegistry.register( "array_concat", new GaussDBArrayConcatFunction() ); + } + /** * Oracle array_concat() function */ @@ -2958,6 +3010,13 @@ public void arrayPrepend_postgresql() { functionRegistry.register( "array_prepend", new PostgreSQLArrayConcatElementFunction( true ) ); } + /** + * GaussDB array_prepend() function + */ + public void arrayPrepend_gaussdb() { + functionRegistry.register( "array_prepend", new GaussDBArrayConcatElementFunction( true ) ); + } + /** * Oracle array_prepend() function */ @@ -2979,6 +3038,13 @@ public void arrayAppend_postgresql() { functionRegistry.register( "array_append", new PostgreSQLArrayConcatElementFunction( false ) ); } + /** + * GaussDB array_append() function + */ + public void arrayAppend_gaussdb() { + functionRegistry.register( "array_append", new GaussDBArrayConcatElementFunction( false ) ); + } + /** * Oracle array_append() function */ @@ -3054,6 +3120,13 @@ public void arraySet_unnest() { functionRegistry.register( "array_set", new ArraySetUnnestFunction() ); } + /** + * GaussDB array_set() function + */ + public void arraySet_gaussdb() { + functionRegistry.register( "array_set", new GaussDBArraySetFunction() ); + } + /** * Oracle array_set() function */ @@ -3084,6 +3157,13 @@ public void arrayRemove_h2(int maximumArraySize) { functionRegistry.register( "array_remove", new H2ArrayRemoveFunction( maximumArraySize ) ); } + /** + * GaussDB array_remove() function + */ + public void arrayRemove_gaussdb() { + functionRegistry.register( "array_remove", new GaussDBArrayRemoveFunction()); + } + /** * HSQL array_remove() function */ @@ -3098,6 +3178,13 @@ public void arrayRemove_oracle() { functionRegistry.register( "array_remove", new OracleArrayRemoveFunction() ); } + /** + * GaussDB array_remove_index() function + */ + public void arrayRemoveIndex_gaussdb() { + functionRegistry.register( "array_remove_index", new GaussDBArrayRemoveIndexFunction(false) ); + } + /** * H2 array_remove_index() function */ @@ -3215,6 +3302,13 @@ public void arrayReplace_oracle() { functionRegistry.register( "array_replace", new OracleArrayReplaceFunction() ); } + /** + * GaussDB array_replace() function + */ + public void arrayReplace_gaussdb() { + functionRegistry.register( "array_replace", new GaussDBArrayReplaceFunction() ); + } + /** * H2, HSQLDB, CockroachDB and PostgreSQL array_trim() function */ @@ -3251,6 +3345,13 @@ public void arrayTrim_oracle() { functionRegistry.register( "array_trim", new OracleArrayTrimFunction() ); } + /** + * GaussDB array_trim() emulation for versions before 14 + */ + public void arrayTrim_gaussdb() { + functionRegistry.register( "array_trim", new GaussDBArrayTrimFunction() ); + } + /** * H2 array_fill() function */ @@ -3275,6 +3376,14 @@ public void arrayFill_postgresql() { functionRegistry.register( "array_fill_list", new PostgreSQLArrayFillFunction( true ) ); } + /** + * GaussDB array_fill() function + */ + public void arrayFill_gaussdb() { + functionRegistry.register( "array_fill", new GaussDBArrayFillFunction( false ) ); + functionRegistry.register( "array_fill_list", new GaussDBArrayFillFunction( true ) ); + } + /** * Cockroach array_fill() function */ @@ -3347,6 +3456,13 @@ public void jsonValue_postgresql(boolean supportsStandard) { functionRegistry.register( "json_value", new PostgreSQLJsonValueFunction( supportsStandard, typeConfiguration ) ); } + /** + * GaussDB json_value() function + */ + public void jsonValue_gaussdb(boolean supportsStandard) { + functionRegistry.register( "json_value", new GaussDBJsonValueFunction( typeConfiguration ) ); + } + /** * CockroachDB json_value() function */ @@ -3389,6 +3505,13 @@ public void jsonQuery() { functionRegistry.register( "json_query", new JsonQueryFunction( typeConfiguration, true, true ) ); } + /** + * GaussDB json_query() function + */ + public void jsonQuery_gaussdb() { + functionRegistry.register( "json_query", new GaussdbJsonQueryFunction( typeConfiguration ) ); + } + /** * json_query() function */ @@ -3452,6 +3575,13 @@ public void jsonExists() { functionRegistry.register( "json_exists", new JsonExistsFunction( typeConfiguration, true, true ) ); } + /** + * json_exists() function + */ + public void jsonExists_gaussdb() { + functionRegistry.register( "json_exists", new GaussdbJsonExistsFunction( typeConfiguration, false, false ) ); + } + /** * json_exists() function that doesn't support the passing clause */ @@ -3564,6 +3694,13 @@ public void jsonObject_postgresql() { functionRegistry.register( "json_object", new PostgreSQLJsonObjectFunction( typeConfiguration ) ); } + /** + * GaussDB json_object() function + */ + public void jsonObject_gaussdb() { + functionRegistry.register( "json_object", new GaussDBJsonObjectFunction( typeConfiguration ) ); + } + /** * json_array() function */ @@ -3592,6 +3729,13 @@ public void jsonArray_sqlserver(boolean supportsExtendedJson) { functionRegistry.register( "json_array", new SQLServerJsonArrayFunction( supportsExtendedJson, typeConfiguration ) ); } + /** + * GaussDB json_array() function + */ + public void jsonArray_gaussdb() { + functionRegistry.register( "json_array", new GaussDBJsonArrayFunction( typeConfiguration ) ); + } + /** * SAP HANA json_array() function */ @@ -3655,6 +3799,13 @@ public void jsonArrayAgg_postgresql(boolean supportsStandard) { functionRegistry.register( "json_arrayagg", new PostgreSQLJsonArrayAggFunction( supportsStandard, typeConfiguration ) ); } + /** + * GaussDB json_arrayagg() function + */ + public void jsonArrayAgg_gaussdb(boolean supportsStandard) { + functionRegistry.register( "json_arrayagg", new GaussDBJsonArrayAggFunction( supportsStandard, typeConfiguration ) ); + } + /** * SQL Server json_arrayagg() function */ @@ -3711,6 +3862,13 @@ public void jsonObjectAgg_postgresql(boolean supportsStandard) { functionRegistry.register( "json_objectagg", new PostgreSQLJsonObjectAggFunction( supportsStandard, typeConfiguration ) ); } + /** + * GaussDB json_objectagg() function + */ + public void jsonObjectAgg_gaussdb(boolean supportsStandard) { + functionRegistry.register( "json_objectagg", new GaussDBJsonObjectAggFunction( supportsStandard, typeConfiguration ) ); + } + /** * MySQL json_objectagg() function */ @@ -3753,6 +3911,13 @@ public void jsonSet_postgresql() { functionRegistry.register( "json_set", new PostgreSQLJsonSetFunction( typeConfiguration ) ); } + /** + * GaussDB json_set() function + */ + public void jsonSet_gaussdb() { + functionRegistry.register( "json_set", new GaussDBJsonSetFunction( typeConfiguration ) ); + } + /** * MySQL json_set() function */ @@ -3791,6 +3956,13 @@ public void jsonRemove_postgresql() { functionRegistry.register( "json_remove", new PostgreSQLJsonRemoveFunction( typeConfiguration ) ); } + /** + * GaussDB json_remove() function + */ + public void jsonRemove_gaussdb() { + functionRegistry.register( "json_remove", new GaussDBJsonRemoveFunction( typeConfiguration ) ); + } + /** * CockroachDB json_remove() function */ @@ -3835,6 +4007,13 @@ public void jsonReplace_postgresql() { functionRegistry.register( "json_replace", new PostgreSQLJsonReplaceFunction( typeConfiguration ) ); } + /** + * GaussDB json_replace() function + */ + public void jsonReplace_gaussdb() { + functionRegistry.register( "json_replace", new GaussDBJsonReplaceFunction( typeConfiguration ) ); + } + /** * MySQL json_replace() function */ @@ -3873,6 +4052,13 @@ public void jsonInsert_postgresql() { functionRegistry.register( "json_insert", new PostgreSQLJsonInsertFunction( typeConfiguration ) ); } + /** + * GaussDB json_insert() function + */ + public void jsonInsert_gaussdb() { + functionRegistry.register( "json_insert", new GaussDBJsonInsertFunction( typeConfiguration ) ); + } + /** * MySQL json_insert() function */ @@ -3911,6 +4097,13 @@ public void jsonMergepatch_postgresql() { functionRegistry.register( "json_mergepatch", new PostgreSQLJsonMergepatchFunction( typeConfiguration ) ); } + /** + * GaussDB json_mergepatch() function + */ + public void jsonMergepatch_gaussdb() { + functionRegistry.register( "json_mergepatch", new GaussDBJsonMergepatchFunction( typeConfiguration ) ); + } + /** * MySQL json_mergepatch() function */ @@ -3941,6 +4134,13 @@ public void jsonArrayAppend_postgresql(boolean supportsLax) { functionRegistry.register( "json_array_append", new PostgreSQLJsonArrayAppendFunction( supportsLax, typeConfiguration ) ); } + /** + * GaussDB json_array_append() function + */ + public void jsonArrayAppend_gaussdb(boolean supportsLax) { + functionRegistry.register( "json_array_append", new GaussDBJsonArrayAppendFunction( supportsLax, typeConfiguration ) ); + } + /** * MySQL json_array_append() function */ @@ -3986,6 +4186,13 @@ public void jsonArrayInsert_postgresql() { functionRegistry.register( "json_array_insert", new PostgreSQLJsonArrayInsertFunction( typeConfiguration ) ); } + /** + * gauss json_array_insert() function + */ + public void jsonArrayInsert_gauss() { + functionRegistry.register( "json_array_insert", new GaussDBJsonArrayInsertFunction( typeConfiguration ) ); + } + /** * MySQL json_array_insert() function */ @@ -4151,6 +4358,13 @@ public void xmlquery_postgresql() { functionRegistry.register( "xmlquery", new PostgreSQLXmlQueryFunction( typeConfiguration ) ); } + /** + * GaussDB xmlquery() function + */ + public void xmlquery_gaussdb() { + functionRegistry.register( "xmlquery", new GaussDBXmlQueryFunction( typeConfiguration ) ); + } + /** * SQL Server xmlquery() function */ diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBFormatFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBFormatFunction.java new file mode 100644 index 000000000000..34ddc3301382 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBFormatFunction.java @@ -0,0 +1,791 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function; + +import org.hibernate.dialect.Dialect; +import org.hibernate.metamodel.mapping.JdbcMappingContainer; +import org.hibernate.metamodel.mapping.MappingModelExpressible; +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.query.common.TemporalUnit; +import org.hibernate.query.spi.QueryEngine; +import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; +import org.hibernate.query.sqm.function.FunctionRenderer; +import org.hibernate.query.sqm.function.MultipatternSqmFunctionDescriptor; +import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression; +import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; +import org.hibernate.query.sqm.function.SqmFunctionDescriptor; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; +import org.hibernate.query.sqm.produce.function.ArgumentsValidator; +import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver; +import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; +import org.hibernate.query.sqm.tree.SqmTypedNode; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.spi.StringBuilderSqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression; +import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression; +import org.hibernate.sql.ast.tree.expression.DurationUnit; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.Format; +import org.hibernate.sql.ast.tree.expression.QueryLiteral; +import org.hibernate.sql.ast.tree.expression.SqlTuple; +import org.hibernate.sql.ast.tree.expression.SqlTupleContainer; +import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate; +import org.hibernate.sql.ast.tree.predicate.LessThanPredicate; +import org.hibernate.type.BasicType; +import org.hibernate.type.SqlTypes; +import org.hibernate.type.StandardBasicTypes; +import org.hibernate.type.spi.TypeConfiguration; + +import java.util.ArrayList; +import java.util.List; + +import static org.hibernate.internal.util.StringHelper.splitFull; +import static org.hibernate.query.sqm.BinaryArithmeticOperator.DIVIDE_PORTABLE; +import static org.hibernate.query.sqm.BinaryArithmeticOperator.MODULO; +import static org.hibernate.query.sqm.ComparisonOperator.GREATER_THAN_OR_EQUAL; +import static org.hibernate.query.sqm.ComparisonOperator.LESS_THAN; +import static org.hibernate.query.sqm.ComparisonOperator.LESS_THAN_OR_EQUAL; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL; +import static org.hibernate.query.sqm.produce.function.StandardArgumentsValidators.exactly; +import static org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers.invariant; +import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.invariant; + +/** + * A format function with support for composite temporal expressions. + * + * @author Christian Beikov + * + * Notes: Original code of this class is based on FormatFunction. + * + */ +public class GaussDBFormatFunction extends AbstractSqmFunctionDescriptor implements FunctionRenderer { + + private final String nativeFunctionName; + private final boolean reversedArguments; + private final boolean concatPattern; + private final boolean supportsTime; + + public GaussDBFormatFunction(String nativeFunctionName, TypeConfiguration typeConfiguration) { + this( nativeFunctionName, false, true, typeConfiguration ); + } + + public GaussDBFormatFunction( + String nativeFunctionName, + boolean reversedArguments, + boolean concatPattern, + TypeConfiguration typeConfiguration) { + this( nativeFunctionName, reversedArguments, concatPattern, true, typeConfiguration ); + } + + public GaussDBFormatFunction( + String nativeFunctionName, + boolean reversedArguments, + boolean concatPattern, + boolean supportsTime, + TypeConfiguration typeConfiguration) { + super( + "format", + new ArgumentTypesValidator( exactly( 2 ), TEMPORAL, STRING ), + invariant( typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ) ), + invariant( typeConfiguration, TEMPORAL, STRING ) + ); + this.nativeFunctionName = nativeFunctionName; + this.reversedArguments = reversedArguments; + this.concatPattern = concatPattern; + this.supportsTime = supportsTime; + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + sqlAppender.appendSql( nativeFunctionName ); + sqlAppender.append( '(' ); + final SqlAstNode expression = sqlAstArguments.get( 0 ); + final SqlAstNode format = sqlAstArguments.get( 1 ); + if ( reversedArguments ) { + format.accept( walker ); + sqlAppender.append( ',' ); + if ( !supportsTime && isTimeTemporal( expression ) ) { + sqlAppender.append( "date'1970-01-01'+" ); + } + expression.accept( walker ); + } + else { + if ( !supportsTime && isTimeTemporal( expression ) ) { + sqlAppender.append( "date'1970-01-01'+" ); + } + expression.accept( walker ); + sqlAppender.append( ',' ); + format.accept( walker ); + } + sqlAppender.append( ')' ); + } + + private boolean isTimeTemporal(SqlAstNode expression) { + if ( expression instanceof Expression ) { + final JdbcMappingContainer expressionType = ( (Expression) expression ).getExpressionType(); + if ( expressionType.getJdbcTypeCount() == 1 ) { + switch ( expressionType.getSingleJdbcMapping().getJdbcType().getDefaultSqlTypeCode() ) { + case SqlTypes.TIME: + case SqlTypes.TIME_WITH_TIMEZONE: + case SqlTypes.TIME_UTC: + return true; + default: + break; + } + } + } + return false; + } + + @Override + protected SelfRenderingSqmFunction generateSqmFunctionExpression( + List> arguments, + ReturnableType impliedResultType, + QueryEngine queryEngine) { + return new FormatSqmFunction<>( + this, + this, + arguments, + impliedResultType, + getArgumentsValidator(), + getReturnTypeResolver(), + concatPattern, + queryEngine + ); + } + + @Override + public String getArgumentListSignature() { + return "(TEMPORAL datetime as STRING pattern)"; + } + + protected static class FormatSqmFunction extends SelfRenderingSqmFunction { + + private final boolean supportsPatternLiterals; + private final TypeConfiguration typeConfiguration; + private QueryEngine queryEngine; + + public FormatSqmFunction( + SqmFunctionDescriptor descriptor, + FunctionRenderer renderer, + List> arguments, + ReturnableType impliedResultType, + ArgumentsValidator argumentsValidator, + FunctionReturnTypeResolver returnTypeResolver, + boolean supportsPatternLiterals, + QueryEngine queryEngine) { + super( + descriptor, + renderer, + arguments, + impliedResultType, + argumentsValidator, + returnTypeResolver, + queryEngine.getCriteriaBuilder(), + "format" + ); + this.supportsPatternLiterals = supportsPatternLiterals; + this.typeConfiguration = queryEngine.getTypeConfiguration(); + this.queryEngine = queryEngine; + } + + @Override + public Expression convertToSqlAst(SqmToSqlAstConverter walker) { + final List arguments = resolveSqlAstArguments( getArguments(), walker ); + final ReturnableType resultType = resolveResultType( walker ); + final MappingModelExpressible mappingModelExpressible = + resultType == null + ? null + : getMappingModelExpressible( walker, resultType, arguments ); + final SqlAstNode expression = arguments.get( 0 ); + if ( expression instanceof SqlTupleContainer ) { + // SqlTupleContainer means this is a composite temporal type i.e. uses `@TimeZoneStorage(COLUMN)` + // The support for this kind of type requires that we inject the offset from the second column + // as literal into the pattern, and apply the formatting on the date time part + final SqlTuple sqlTuple = ( (SqlTupleContainer) expression ).getSqlTuple(); + final FunctionRenderer timestampaddFunction = getFunction( walker, "timestampadd" ); + final BasicType integerType = typeConfiguration.getBasicTypeRegistry() + .resolve( StandardBasicTypes.INTEGER ); + arguments.set( 0, getOffsetAdjusted( sqlTuple, timestampaddFunction, integerType ) ); + if ( getArgumentsValidator() != null ) { + getArgumentsValidator().validateSqlTypes( arguments, getFunctionName() ); + } + final Format format = (Format) arguments.get( 1 ); + // If the format contains a time zone or offset, we must replace that with the offset column + if ( format.getFormat().contains( "x" ) || !supportsPatternLiterals ) { + final FunctionRenderer concatFunction = getFunction( walker, "concat" ); + final FunctionRenderer substringFunction = getFunction( walker, "substring", 3 ); + final BasicType stringType = typeConfiguration.getBasicTypeRegistry() + .resolve( StandardBasicTypes.STRING ); + final Dialect dialect = walker.getCreationContext().getDialect(); + Expression formatExpression = null; + final StringBuilder sb = new StringBuilder(); + final StringBuilderSqlAppender sqlAppender = new StringBuilderSqlAppender( sb ); + final String delimiter; + if ( supportsPatternLiterals ) { + dialect.appendDatetimeFormat( sqlAppender, "'a'" ); + delimiter = sb.substring( 0, sb.indexOf( "a" ) ).replace( "''", "'" ); + } + else { + delimiter = ""; + } + final String[] chunks = splitFull( "'", format.getFormat() ); + final Expression offsetExpression = sqlTuple.getExpressions().get( 1 ); + // Splitting by `'` will put actual format pattern parts to even indices and literal pattern parts + // to uneven indices. We will only replace the time zone and offset pattern in the format pattern parts + for ( int i = 0; i < chunks.length; i += 2 ) { + // The general idea is to replace the various patterns `xxx`, `xx` and `x` by concatenating + // the offset column as literal i.e. `HH:mmxxx` is translated to `HH:mm'''||offset||'''` + // xxx stands for the full offset i.e. `+01:00` + // xx stands for the medium offset i.e. `+0100` + // x stands for the small offset i.e. `+01` + final String[] fullParts = splitFull( "xxx", chunks[i] ); + for ( int j = 0; j < fullParts.length; j++ ) { + if ( fullParts[j].isEmpty() ) { + continue; + } + final String[] mediumParts = splitFull( "xx", fullParts[j] ); + for ( int k = 0; k < mediumParts.length; k++ ) { + if ( mediumParts[k].isEmpty() ) { + continue; + } + final String[] smallParts = splitFull( "x", mediumParts[k] ); + for ( int l = 0; l < smallParts.length; l++ ) { + if ( smallParts[l].isEmpty() ) { + continue; + } + sb.setLength( 0 ); + dialect.appendDatetimeFormat( sqlAppender, smallParts[l] ); + final String formatPart = sb.toString(); + if ( supportsPatternLiterals ) { + formatExpression = concat( + concatFunction, + stringType, + formatExpression, + new QueryLiteral<>( formatPart, stringType ) + ); + } + else { + formatExpression = concat( + concatFunction, + stringType, + formatExpression, + new SelfRenderingFunctionSqlAstExpression( + getFunctionName(), + getFunctionRenderer(), + List.of( + arguments.get( 0 ), + new QueryLiteral<>( formatPart, stringType ) + ), + resultType, + mappingModelExpressible + ) + ); + } + if ( l + 1 < smallParts.length ) { + // This is for `x` patterns, which require `+01` + // so we concat `substring(offset, 1, 4)` + // Since the offset is always in the full format + formatExpression = concatAsLiteral( + concatFunction, + stringType, + delimiter, + formatExpression, + createSmallOffset( + concatFunction, + substringFunction, + stringType, + integerType, + offsetExpression + ) + ); + } + } + if ( k + 1 < mediumParts.length ) { + // This is for `xx` patterns, which require `+0100` + // so we concat `substring(offset, 1, 4)||substring(offset, 4, 6)` + // Since the offset is always in the full format + formatExpression = concatAsLiteral( + concatFunction, + stringType, + delimiter, + formatExpression, + createMediumOffset( + concatFunction, + substringFunction, + stringType, + integerType, + offsetExpression + ) + ); + } + } + if ( j + 1 < fullParts.length ) { + formatExpression = concatAsLiteral( + concatFunction, + stringType, + delimiter, + formatExpression, + createFullOffset( + concatFunction, + stringType, + integerType, + offsetExpression + ) + ); + } + } + + if ( i + 1 < chunks.length ) { + // Handle the pattern literal content + final String formatLiteralPart; + if ( supportsPatternLiterals ) { + sb.setLength( 0 ); + dialect.appendDatetimeFormat( sqlAppender, "'" + chunks[i + 1] + "'" ); + formatLiteralPart = sb.toString().replace( "''", "'" ); + } + else { + formatLiteralPart = chunks[i + 1]; + } + formatExpression = concat( + concatFunction, + stringType, + formatExpression, + new QueryLiteral<>( + formatLiteralPart, + stringType + ) + ); + } + } + + if ( supportsPatternLiterals ) { + arguments.set( 1, formatExpression ); + } + else { + return formatExpression; + } + } + } + else { + if ( getArgumentsValidator() != null ) { + getArgumentsValidator().validateSqlTypes( arguments, getFunctionName() ); + } + + if ( !supportsPatternLiterals ) { + final FunctionRenderer concatFunction = getFunction( walker, "concat" ); + final BasicType stringType = typeConfiguration.getBasicTypeRegistry() + .resolve( StandardBasicTypes.STRING ); + Expression formatExpression = null; + final Format format = (Format) arguments.get( 1 ); + final String[] chunks = splitFull( "'", format.getFormat() ); + // Splitting by `'` will put actual format pattern parts to even indices and literal pattern parts + // to uneven indices. We need to apply the format parts and then concatenate because the pattern + // doesn't support literals + for ( int i = 0; i < chunks.length; i += 2 ) { + formatExpression = concat( + concatFunction, + stringType, + formatExpression, + new SelfRenderingFunctionSqlAstExpression( + getFunctionName(), + getFunctionRenderer(), + List.of( arguments.get( 0 ), new Format( chunks[i] ) ), + resultType, + mappingModelExpressible + ) + ); + if ( i + 1 < chunks.length ) { + // Handle the pattern literal content + formatExpression = concat( + concatFunction, + stringType, + formatExpression, + new QueryLiteral<>( chunks[i + 1], stringType ) + ); + } + } + return formatExpression; + } + } + return new SelfRenderingFunctionSqlAstExpression( + getFunctionName(), + getFunctionRenderer(), + arguments, + resultType, + mappingModelExpressible + ); + } + + private FunctionRenderer getFunction(SqmToSqlAstConverter walker, String name) { + return (FunctionRenderer) + walker.getCreationContext().getSqmFunctionRegistry().findFunctionDescriptor( name ); + } + + private FunctionRenderer getFunction(SqmToSqlAstConverter walker, String name, int argumentCount) { + final SqmFunctionDescriptor functionDescriptor = + walker.getCreationContext().getSqmFunctionRegistry() + .findFunctionDescriptor( name ); + if ( functionDescriptor instanceof MultipatternSqmFunctionDescriptor multipatternSqmFunctionDescriptor ) { + return (FunctionRenderer) multipatternSqmFunctionDescriptor.getFunction( argumentCount ); + } + else { + return (FunctionRenderer) functionDescriptor; + } + } + + private SqlAstNode getOffsetAdjusted( + SqlTuple sqlTuple, + FunctionRenderer timestampaddFunction, + BasicType integerType) { + final Expression instantExpression = sqlTuple.getExpressions().get( 0 ); + final Expression offsetExpression = sqlTuple.getExpressions().get( 1 ); + + return new SelfRenderingFunctionSqlAstExpression( + "timestampadd", + timestampaddFunction, + List.of( + new DurationUnit( TemporalUnit.SECOND, integerType ), + offsetExpression, + instantExpression + ), + (ReturnableType) instantExpression.getExpressionType(), + instantExpression.getExpressionType() + ); + } + + private Expression createFullOffset( + FunctionRenderer concatFunction, + BasicType stringType, + BasicType integerType, + Expression offsetExpression) { + if ( offsetExpression.getExpressionType().getSingleJdbcMapping().getJdbcType().isString() ) { + return offsetExpression; + } + else { + // ZoneOffset as seconds + final CaseSearchedExpression caseSearchedExpression = + zoneOffsetSeconds( stringType, integerType, offsetExpression ); + final Expression hours = getHours( integerType, offsetExpression ); + final Expression minutes = getMinutes( integerType, offsetExpression ); + + final CaseSearchedExpression minuteStart = new CaseSearchedExpression( stringType ); + minuteStart.getWhenFragments().add( + new CaseSearchedExpression.WhenFragment( + new LessThanPredicate( + minutes, + new QueryLiteral<>( 10, integerType ), + false, + null + ), + new QueryLiteral<>( ":0", stringType ) + ) + ); + minuteStart.otherwise( new QueryLiteral<>( ":", stringType ) ); + return concat( + concatFunction, + stringType, + concat( + concatFunction, + stringType, + concat( concatFunction, stringType, caseSearchedExpression, hours ), + minuteStart + ), + minutes + ); + } + } + + private Expression createMediumOffset( + FunctionRenderer concatFunction, + FunctionRenderer substringFunction, + BasicType stringType, + BasicType integerType, + Expression offsetExpression) { + if ( offsetExpression.getExpressionType().getSingleJdbcMapping().getJdbcType().isString() ) { + return concat( + concatFunction, + stringType, + createSmallOffset( + concatFunction, + substringFunction, + stringType, + integerType, + offsetExpression + ), + new SelfRenderingFunctionSqlAstExpression( + "substring", + substringFunction, + List.of( + offsetExpression, + new QueryLiteral<>( 4, integerType ), + new QueryLiteral<>( 6, integerType ) + ), + stringType, + stringType + ) + ); + } + else { + // ZoneOffset as seconds + final CaseSearchedExpression caseSearchedExpression = + zoneOffsetSeconds( stringType, integerType, offsetExpression ); + + final Expression hours = getHours( integerType, offsetExpression ); + final Expression minutes = getMinutes( integerType, offsetExpression ); + + final CaseSearchedExpression minuteStart = new CaseSearchedExpression( stringType ); + minuteStart.getWhenFragments().add( + new CaseSearchedExpression.WhenFragment( + new LessThanPredicate( + minutes, + new QueryLiteral<>( 10, integerType ), + false, + null + ), + new QueryLiteral<>( "0", stringType ) + ) + ); + minuteStart.otherwise( new QueryLiteral<>( "", stringType ) ); + return concat( + concatFunction, + stringType, + concat( + concatFunction, + stringType, + concat( concatFunction, stringType, caseSearchedExpression, hours ), + minuteStart + ), + minutes + ); + } + } + + private Expression createSmallOffset( + FunctionRenderer concatFunction, + FunctionRenderer substringFunction, + BasicType stringType, + BasicType integerType, + Expression offsetExpression) { + if ( offsetExpression.getExpressionType().getSingleJdbcMapping().getJdbcType().isString() ) { + return new SelfRenderingFunctionSqlAstExpression( + "substring", + substringFunction, + List.of( + offsetExpression, + new QueryLiteral<>( 1, integerType ), + new QueryLiteral<>( 4, integerType ) + ), + stringType, + stringType + ); + } + else { + // ZoneOffset as seconds + final CaseSearchedExpression caseSearchedExpression = + zoneOffsetSeconds( stringType, integerType, offsetExpression ); + final Expression hours = getHours( integerType, offsetExpression ); + return concat( concatFunction, stringType, caseSearchedExpression, hours ); + } + } + + private Expression concatAsLiteral( + FunctionRenderer concatFunction, + BasicType stringType, + String delimiter, + Expression expression, + Expression expression2) { + return concat( + concatFunction, + stringType, + concat( + concatFunction, + stringType, + concat( + concatFunction, + stringType, + expression, + new QueryLiteral<>( delimiter, stringType ) + ), + expression2 + ), + new QueryLiteral<>( delimiter, stringType ) + ); + } + + private Expression concat( + FunctionRenderer concatFunction, + BasicType stringType, + Expression expression, + Expression expression2) { + if ( expression == null ) { + return expression2; + } + else if ( expression instanceof SelfRenderingFunctionSqlAstExpression selfRenderingFunction + && "concat".equals( selfRenderingFunction.getFunctionName() ) ) { + final List list = (List) selfRenderingFunction.getArguments(); + final SqlAstNode lastOperand = list.get( list.size() - 1 ); + if ( expression2 instanceof QueryLiteral literal2 + && lastOperand instanceof QueryLiteral literalOperand ) { + list.set( + list.size() - 1, + new QueryLiteral<>( + literalOperand.getLiteralValue().toString() + + literal2.getLiteralValue().toString(), + stringType + ) + ); + } + else { + list.add( expression2 ); + } + return expression; + } + else if ( expression2 instanceof SelfRenderingFunctionSqlAstExpression selfRenderingFunction + && "concat".equals( selfRenderingFunction.getFunctionName() ) ) { + final List list = (List) selfRenderingFunction.getArguments(); + final SqlAstNode firstOperand = list.get( 0 ); + if ( expression instanceof QueryLiteral literal + && firstOperand instanceof QueryLiteral literalOperand ) { + list.set( + list.size() - 1, + new QueryLiteral<>( + literal.getLiteralValue().toString() + + literalOperand.getLiteralValue().toString(), + stringType + ) + ); + } + else { + list.add( 0, expression ); + } + return expression2; + } + else if ( expression instanceof QueryLiteral literal + && expression2 instanceof QueryLiteral literal2 ) { + return new QueryLiteral<>( + literal.getLiteralValue().toString() + + literal2.getLiteralValue().toString(), + stringType + ); + } + else { + final List list = new ArrayList<>( 2 ); + list.add( expression ); + list.add( expression2 ); + return new SelfRenderingFunctionSqlAstExpression( + "concat", + concatFunction, + list, + stringType, + stringType + ); + } + } + + private Expression getHours( + BasicType integerType, + Expression offsetExpression) { + BinaryArithmeticExpression divisionExpr = new BinaryArithmeticExpression( + offsetExpression, + DIVIDE_PORTABLE, + new QueryLiteral<>(3600, integerType), + integerType + ); + return floor(divisionExpr); + } + + private Expression getMinutes( + BasicType integerType, + Expression offsetExpression){ + return new BinaryArithmeticExpression( + abs(new BinaryArithmeticExpression( + offsetExpression, + MODULO, + new QueryLiteral<>( 3600, integerType ), + integerType + )), + DIVIDE_PORTABLE, + new QueryLiteral<>( 60, integerType ), + integerType + ); + } + + private Expression abs(Expression expression) { + return new SelfRenderingFunctionSqlAstExpression( + "abs", + findSelfRenderingFunction( "abs", 2 ), + List.of( expression ), + (ReturnableType) expression.getExpressionType(), + expression.getExpressionType() + ); + } + + private Expression floor(Expression expression) { + return new SelfRenderingFunctionSqlAstExpression( + "floor", + findSelfRenderingFunction( "floor", 2 ), + List.of( expression ), + (ReturnableType) expression.getExpressionType(), + expression.getExpressionType() + ); + } + + private FunctionRenderer findSelfRenderingFunction(String functionName, int argumentCount) { + final SqmFunctionDescriptor functionDescriptor = + queryEngine.getSqmFunctionRegistry() + .findFunctionDescriptor( functionName ); + if ( functionDescriptor instanceof MultipatternSqmFunctionDescriptor multiPatternFunction ) { + return (FunctionRenderer) multiPatternFunction.getFunction( argumentCount ); + } + return (FunctionRenderer) functionDescriptor; + } + } + + private static CaseSearchedExpression zoneOffsetSeconds(BasicType stringType, BasicType integerType, Expression offsetExpression) { + final CaseSearchedExpression caseSearchedExpression = new CaseSearchedExpression(stringType); + caseSearchedExpression.getWhenFragments().add( + new CaseSearchedExpression.WhenFragment( + new ComparisonPredicate( + offsetExpression, + LESS_THAN_OR_EQUAL, + new QueryLiteral<>( -36000, integerType) + ), + new QueryLiteral<>( "-", stringType) + ) + ); + caseSearchedExpression.getWhenFragments().add( + new CaseSearchedExpression.WhenFragment( + new ComparisonPredicate( + offsetExpression, + LESS_THAN, + new QueryLiteral<>( 0, integerType) + ), + new QueryLiteral<>( "-0", stringType) + ) + ); + caseSearchedExpression.getWhenFragments().add( + new CaseSearchedExpression.WhenFragment( + new ComparisonPredicate( + offsetExpression, + GREATER_THAN_OR_EQUAL, + new QueryLiteral<>( 36000, integerType) + ), + new QueryLiteral<>( "+", stringType) + ) + ); + caseSearchedExpression.otherwise( new QueryLiteral<>( "+0", stringType) ); + return caseSearchedExpression; + } + + +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBMinMaxFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBMinMaxFunction.java new file mode 100644 index 000000000000..6603e4d230c7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBMinMaxFunction.java @@ -0,0 +1,116 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function; + +import java.util.List; + +import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; +import org.hibernate.query.sqm.function.FunctionKind; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; +import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; +import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; +import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; +import org.hibernate.sql.ast.Clause; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.predicate.Predicate; +import org.hibernate.type.SqlTypes; + +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.COMPARABLE; + +/** + * GaussDB doesn't support min/max for uuid yet, + * but since that type is comparable we want to support this operation. + * The workaround is to cast uuid to text and aggregate that, which preserves the ordering, + * and finally cast the result back to uuid. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLDialect. + */ +public class GaussDBMinMaxFunction extends AbstractSqmSelfRenderingFunctionDescriptor { + + public GaussDBMinMaxFunction(String name) { + super( + name, + FunctionKind.AGGREGATE, + new ArgumentTypesValidator( StandardArgumentsValidators.exactly( 1 ), COMPARABLE ), + StandardFunctionReturnTypeResolvers.useFirstNonNull(), + StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE + ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + render( sqlAppender, sqlAstArguments, null, returnType, walker ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + Predicate filter, + ReturnableType returnType, + SqlAstTranslator translator) { + final boolean caseWrapper = filter != null && !translator.getSessionFactory().getJdbcServices().getDialect().supportsFilterClause(); + sqlAppender.appendSql( getName() ); + sqlAppender.appendSql( '(' ); + final Expression arg = (Expression) sqlAstArguments.get( 0 ); + final String castTarget; + if ( caseWrapper ) { + translator.getCurrentClauseStack().push( Clause.WHERE ); + sqlAppender.appendSql( "case when " ); + filter.accept( translator ); + translator.getCurrentClauseStack().pop(); + sqlAppender.appendSql( " then " ); + castTarget = renderArgument( sqlAppender, translator, arg ); + sqlAppender.appendSql( " else null end)" ); + } + else { + castTarget = renderArgument( sqlAppender, translator, arg ); + sqlAppender.appendSql( ')' ); + if ( filter != null ) { + translator.getCurrentClauseStack().push( Clause.WHERE ); + sqlAppender.appendSql( " filter (where " ); + filter.accept( translator ); + sqlAppender.appendSql( ')' ); + translator.getCurrentClauseStack().pop(); + } + } + if ( castTarget != null ) { + sqlAppender.appendSql( "::" ); + sqlAppender.appendSql( castTarget ); + } + } + + private String renderArgument(SqlAppender sqlAppender, SqlAstTranslator translator, Expression arg) { + final JdbcMapping sourceMapping = arg.getExpressionType().getSingleJdbcMapping(); + // Cast uuid expressions to "text" first, aggregate that, and finally cast to uuid again + if ( sourceMapping.getJdbcType().getDefaultSqlTypeCode() == SqlTypes.UUID ) { + sqlAppender.appendSql( "cast(" ); + arg.accept( translator ); + sqlAppender.appendSql( " as text)" ); + return "uuid"; + } + else { + arg.accept( translator ); + return null; + } + } + + @Override + public String getArgumentListSignature() { + return "(COMPARABLE arg)"; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBTruncFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBTruncFunction.java new file mode 100644 index 000000000000..9c0a7735200e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBTruncFunction.java @@ -0,0 +1,64 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.query.spi.QueryEngine; +import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; +import org.hibernate.query.sqm.tree.SqmTypedNode; +import org.hibernate.query.sqm.tree.expression.SqmExtractUnit; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * Custom {@link TruncFunction} for GaussDB which uses the dialect-specific function for numeric truncation + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLTruncFunction. + */ +public class GaussDBTruncFunction extends TruncFunction { + private final GaussDBTruncRoundFunction gaussDBTruncRoundFunction; + + public GaussDBTruncFunction(boolean supportsTwoArguments, TypeConfiguration typeConfiguration) { + super( + "trunc(?1)", + null, + DatetimeTrunc.DATE_TRUNC, + null, + typeConfiguration + ); + this.gaussDBTruncRoundFunction = new GaussDBTruncRoundFunction( "trunc", supportsTwoArguments ); + } + + @Override + protected SelfRenderingSqmFunction generateSqmFunctionExpression( + List> arguments, + ReturnableType impliedResultType, + QueryEngine queryEngine) { + final List> args = new ArrayList<>( arguments ); + if ( arguments.size() != 2 || !( arguments.get( 1 ) instanceof SqmExtractUnit ) ) { + // numeric truncation + return gaussDBTruncRoundFunction.generateSqmFunctionExpression( + arguments, + impliedResultType, + queryEngine + ); + } + // datetime truncation + return new SelfRenderingSqmFunction<>( + this, + datetimeRenderingSupport, + args, + impliedResultType, + TruncArgumentsValidator.DATETIME_VALIDATOR, + getReturnTypeResolver(), + queryEngine.getCriteriaBuilder(), + getName() + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBTruncRoundFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBTruncRoundFunction.java new file mode 100644 index 000000000000..62e61765e6b4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/GaussDBTruncRoundFunction.java @@ -0,0 +1,124 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.query.spi.QueryEngine; +import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; +import org.hibernate.query.sqm.function.FunctionRenderer; +import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; +import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; +import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; +import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; +import org.hibernate.query.sqm.tree.SqmTypedNode; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.type.descriptor.jdbc.JdbcType; + +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.NUMERIC; + +/** + * GaussDB only supports the two-argument {@code trunc} and {@code round} functions + * with the following signatures: + *
    + *
  • {@code trunc(numeric, integer)}
  • + *
  • {@code round(numeric, integer)}
  • + *
+ *

+ * This custom function falls back to using {@code floor} as a workaround only when necessary, + * e.g. when there are 2 arguments to the function and either: + *

    + *
  • The first argument is not of type {@code numeric}
  • + * or + *
  • The dialect doesn't support the two-argument {@code trunc} function
  • + *
+ * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLTruncRoundFunction. + */ +public class GaussDBTruncRoundFunction extends AbstractSqmFunctionDescriptor implements FunctionRenderer { + private final boolean supportsTwoArguments; + + public GaussDBTruncRoundFunction(String name, boolean supportsTwoArguments) { + super( + name, + new ArgumentTypesValidator( StandardArgumentsValidators.between( 1, 2 ), NUMERIC, INTEGER ), + StandardFunctionReturnTypeResolvers.useArgType( 1 ), + StandardFunctionArgumentTypeResolvers.invariant( NUMERIC, INTEGER ) + ); + this.supportsTwoArguments = supportsTwoArguments; + } + + @Override + public void render( + SqlAppender sqlAppender, + List arguments, + ReturnableType returnType, + SqlAstTranslator walker) { + final int numberOfArguments = arguments.size(); + final Expression firstArg = (Expression) arguments.get( 0 ); + final JdbcType jdbcType = firstArg.getExpressionType().getSingleJdbcMapping().getJdbcType(); + if ( numberOfArguments == 1 || supportsTwoArguments && jdbcType.isDecimal() ) { + // use native two-argument function + sqlAppender.appendSql( getName() ); + sqlAppender.appendSql( "(" ); + firstArg.accept( walker ); + if ( numberOfArguments > 1 ) { + sqlAppender.appendSql( ", " ); + arguments.get( 1 ).accept( walker ); + } + sqlAppender.appendSql( ")" ); + } + else { + // workaround using floor + if ( getName().equals( "trunc" ) ) { + sqlAppender.appendSql( "sign(" ); + firstArg.accept( walker ); + sqlAppender.appendSql( ")*floor(abs(" ); + firstArg.accept( walker ); + sqlAppender.appendSql( ")*1e" ); + arguments.get( 1 ).accept( walker ); + } + else { + sqlAppender.appendSql( "floor(" ); + firstArg.accept( walker ); + sqlAppender.appendSql( "*1e" ); + arguments.get( 1 ).accept( walker ); + sqlAppender.appendSql( "+0.5" ); + } + sqlAppender.appendSql( ")/1e" ); + arguments.get( 1 ).accept( walker ); + } + } + + @Override + public String getArgumentListSignature() { + return "(NUMERIC number[, INTEGER places])"; + } + + @Override + protected SelfRenderingSqmFunction generateSqmFunctionExpression( + List> arguments, + ReturnableType impliedResultType, + QueryEngine queryEngine) { + return new SelfRenderingSqmFunction<>( + this, + this, + arguments, + impliedResultType, + getArgumentsValidator(), + getReturnTypeResolver(), + queryEngine.getCriteriaBuilder(), + getName() + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayRemoveIndexUnnestFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayRemoveIndexUnnestFunction.java index 74d88eab2f87..65ab05672969 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayRemoveIndexUnnestFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayRemoveIndexUnnestFunction.java @@ -24,7 +24,7 @@ */ public class ArrayRemoveIndexUnnestFunction extends AbstractSqmSelfRenderingFunctionDescriptor { - private final boolean castEmptyArrayLiteral; + protected final boolean castEmptyArrayLiteral; public ArrayRemoveIndexUnnestFunction(boolean castEmptyArrayLiteral) { super( diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayConcatElementFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayConcatElementFunction.java new file mode 100644 index 000000000000..c25eb4b12dc6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayConcatElementFunction.java @@ -0,0 +1,99 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import java.util.List; + +import org.hibernate.engine.jdbc.Size; +import org.hibernate.metamodel.mapping.JdbcMappingContainer; +import org.hibernate.metamodel.mapping.SqlTypedMapping; +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstNodeRenderingMode; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.Literal; +import org.hibernate.type.BasicPluralType; + +/** + * GaussDB variant of the function to properly return {@code null} when the array argument is null. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLArrayConcatElementFunction. + */ +public class GaussDBArrayConcatElementFunction extends ArrayConcatElementFunction { + + public GaussDBArrayConcatElementFunction(boolean prepend) { + super( "", "||", "", prepend ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + final Expression firstArgument = (Expression) sqlAstArguments.get( 0 ); + final Expression secondArgument = (Expression) sqlAstArguments.get( 1 ); + final Expression arrayArgument; + final Expression elementArgument; + if ( prepend ) { + elementArgument = firstArgument; + arrayArgument = secondArgument; + } + else { + arrayArgument = firstArgument; + elementArgument = secondArgument; + } + final String elementCastType; + if ( needsElementCasting( elementArgument ) ) { + final JdbcMappingContainer arrayType = arrayArgument.getExpressionType(); + final Size size = arrayType instanceof SqlTypedMapping ? ( (SqlTypedMapping) arrayType ).toSize() : null; + elementCastType = DdlTypeHelper.getCastTypeName( + ( (BasicPluralType) returnType ).getElementType(), + size, + walker.getSessionFactory().getTypeConfiguration() + ); + } + else { + elementCastType = null; + } + sqlAppender.append( "case when " ); + walker.render( arrayArgument, SqlAstNodeRenderingMode.DEFAULT ); + sqlAppender.append( " is not null then " ); + if ( prepend && elementCastType != null) { + sqlAppender.append( "cast(" ); + walker.render( firstArgument, SqlAstNodeRenderingMode.DEFAULT ); + sqlAppender.append( " as " ); + sqlAppender.append( elementCastType ); + sqlAppender.append( ')' ); + } + else { + walker.render( firstArgument, SqlAstNodeRenderingMode.DEFAULT ); + } + sqlAppender.append( "||" ); + if ( !prepend && elementCastType != null) { + sqlAppender.append( "cast(" ); + walker.render( secondArgument, SqlAstNodeRenderingMode.DEFAULT ); + sqlAppender.append( " as " ); + sqlAppender.append( elementCastType ); + sqlAppender.append( ')' ); + } + else { + walker.render( secondArgument, SqlAstNodeRenderingMode.DEFAULT ); + } + sqlAppender.append( " end" ); + } + + private static boolean needsElementCasting(Expression elementExpression) { + // GaussDB needs casting of null and string literal expressions + return elementExpression instanceof Literal && ( + elementExpression.getExpressionType().getSingleJdbcMapping().getJdbcType().isString() + || ( (Literal) elementExpression ).getLiteralValue() == null + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayConcatFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayConcatFunction.java new file mode 100644 index 000000000000..b09fea3db34b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayConcatFunction.java @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; + +/** + * GaussDB variant of the function to properly return {@code null} when one of the arguments is null. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLArrayConcatFunction. + */ +public class GaussDBArrayConcatFunction extends ArrayConcatFunction { + + public GaussDBArrayConcatFunction() { + super( "", "||", "" ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + sqlAppender.append( "case when " ); + String separator = ""; + for ( SqlAstNode node : sqlAstArguments ) { + sqlAppender.append( separator ); + node.accept( walker ); + sqlAppender.append( " is not null" ); + separator = " and "; + } + + sqlAppender.append( " then " ); + super.render( sqlAppender, sqlAstArguments, returnType, walker ); + sqlAppender.append( " end" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayConstructorFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayConstructorFunction.java new file mode 100644 index 000000000000..2712f2ec4b93 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayConstructorFunction.java @@ -0,0 +1,59 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.type.BasicPluralType; +import org.hibernate.type.BasicType; + +/** + * Special array constructor function that also applies a cast to the array literal, + * based on the inferred result type. GaussDB needs this, + * because by default it assumes a {@code text[]}, which is not compatible with {@code varchar[]}. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLArrayConstructorFunction. + */ +public class GaussDBArrayConstructorFunction extends ArrayConstructorFunction { + + public GaussDBArrayConstructorFunction(boolean list) { + super( list, true ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + String arrayTypeName = null; + if ( returnType instanceof BasicPluralType pluralType ) { + if ( needsArrayCasting( pluralType.getElementType() ) ) { + arrayTypeName = DdlTypeHelper.getCastTypeName( + returnType, + walker.getSessionFactory().getTypeConfiguration() + ); + sqlAppender.append( "cast(" ); + } + } + super.render( sqlAppender, sqlAstArguments, returnType, walker ); + if ( arrayTypeName != null ) { + sqlAppender.appendSql( " as " ); + sqlAppender.appendSql( arrayTypeName ); + sqlAppender.appendSql( ')' ); + } + } + + private static boolean needsArrayCasting(BasicType elementType) { + // GaussDB doesn't do implicit conversion between text[] and varchar[], so we need casting + return elementType.getJdbcType().isString(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayContainsOperatorFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayContainsOperatorFunction.java new file mode 100644 index 000000000000..f93e94efce5c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayContainsOperatorFunction.java @@ -0,0 +1,86 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.metamodel.mapping.JdbcMappingContainer; +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.type.BasicPluralType; +import org.hibernate.type.spi.TypeConfiguration; + +import java.util.List; + +/** + * Special array contains function that also applies a cast to the element argument. PostgreSQL needs this, + * because by default it assumes a {@code text[]}, which is not compatible with {@code varchar[]}. + * + * Notes: Original code of this class is based on ArrayContainsOperatorFunction. + */ +public class GaussDBArrayContainsOperatorFunction extends ArrayContainsUnnestFunction { + + public GaussDBArrayContainsOperatorFunction(boolean nullable, TypeConfiguration typeConfiguration) { + super( nullable, typeConfiguration ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 ); + final Expression needleExpression = (Expression) sqlAstArguments.get( 1 ); + final JdbcMappingContainer needleTypeContainer = needleExpression.getExpressionType(); + final JdbcMapping needleType = needleTypeContainer == null ? null : needleTypeContainer.getSingleJdbcMapping(); + if ( needleType == null || needleType instanceof BasicPluralType ) { + LOG.deprecatedArrayContainsWithArray(); + if ( nullable ) { + super.render( sqlAppender, sqlAstArguments, returnType, walker ); + } + else { + haystackExpression.accept( walker ); + sqlAppender.append( "@>" ); + needleExpression.accept( walker ); + } + } + else { + if ( nullable ) { + sqlAppender.append( "(array_positions(" ); + haystackExpression.accept( walker ); + sqlAppender.append( ',' ); + needleExpression.accept( walker ); + sqlAppender.append( "))[1] is not null" ); + } + else { + haystackExpression.accept( walker ); + sqlAppender.append( "@>" ); + if ( needsArrayCasting( needleExpression ) ) { + sqlAppender.append( "cast(array[" ); + needleExpression.accept( walker ); + sqlAppender.append( "] as " ); + sqlAppender.append( DdlTypeHelper.getCastTypeName( + haystackExpression.getExpressionType(), + walker.getSessionFactory().getTypeConfiguration() + ) ); + sqlAppender.append( ')' ); + } + else { + sqlAppender.append( "array[" ); + needleExpression.accept( walker ); + sqlAppender.append( ']' ); + } + } + } + } + + private static boolean needsArrayCasting(Expression elementExpression) { + // Gauss doesn't do implicit conversion between text[] and varchar[], so we need casting + return elementExpression.getExpressionType().getSingleJdbcMapping().getJdbcType().isString(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayFillFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayFillFunction.java new file mode 100644 index 000000000000..f3243bd0eb58 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayFillFunction.java @@ -0,0 +1,66 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.Literal; + +/** + * Custom casting for the array fill function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLArrayFillFunction. + */ +public class GaussDBArrayFillFunction extends AbstractArrayFillFunction { + + public GaussDBArrayFillFunction(boolean list) { + super( list ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + sqlAppender.append( "array_fill(" ); + final String elementCastType; + final Expression elementExpression = (Expression) sqlAstArguments.get( 0 ); + if ( needsElementCasting( elementExpression ) ) { + elementCastType = DdlTypeHelper.getCastTypeName( + elementExpression.getExpressionType(), + walker.getSessionFactory().getTypeConfiguration() + ); + sqlAppender.append( "cast(" ); + } + else { + elementCastType = null; + } + sqlAstArguments.get( 0 ).accept( walker ); + if ( elementCastType != null ) { + sqlAppender.append( " as " ); + sqlAppender.append( elementCastType ); + sqlAppender.append( ')' ); + } + sqlAppender.append( ",array[" ); + sqlAstArguments.get( 1 ).accept( walker ); + sqlAppender.append( "])" ); + } + + private static boolean needsElementCasting(Expression elementExpression) { + // GaussDB needs casting of null and string literal expressions + return elementExpression instanceof Literal && ( + elementExpression.getExpressionType().getSingleJdbcMapping().getJdbcType().isString() + || ( (Literal) elementExpression ).getLiteralValue() == null + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayPositionFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayPositionFunction.java new file mode 100644 index 000000000000..c1db4df41aa0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayPositionFunction.java @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstNodeRenderingMode; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB variant of the function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLArrayPositionFunction. + */ +public class GaussDBArrayPositionFunction extends AbstractArrayPositionFunction { + + public GaussDBArrayPositionFunction(TypeConfiguration typeConfiguration) { + super( typeConfiguration ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); + final Expression elementExpression = (Expression) sqlAstArguments.get( 1 ); + + sqlAppender.append( "(array_positions(" ); + arrayExpression.accept( walker ); + sqlAppender.append( ", " ); + walker.render( elementExpression, SqlAstNodeRenderingMode.DEFAULT ); + sqlAppender.append( "))[1]" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayPositionsFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayPositionsFunction.java new file mode 100644 index 000000000000..8b3b8b2643cc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayPositionsFunction.java @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstNodeRenderingMode; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB variant of the function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLArrayPositionsFunction. + */ +public class GaussDBArrayPositionsFunction extends AbstractArrayPositionsFunction { + + public GaussDBArrayPositionsFunction(boolean list, TypeConfiguration typeConfiguration) { + super( list, typeConfiguration ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); + final Expression elementExpression = (Expression) sqlAstArguments.get( 1 ); + sqlAppender.append( "array_positions(" ); + walker.render( arrayExpression, SqlAstNodeRenderingMode.DEFAULT ); + sqlAppender.append( ',' ); + walker.render( elementExpression, SqlAstNodeRenderingMode.DEFAULT ); + sqlAppender.append( ')' ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayRemoveFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayRemoveFunction.java new file mode 100644 index 000000000000..4882f57dd959 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayRemoveFunction.java @@ -0,0 +1,63 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.Literal; + +import java.util.List; + +/** + * Gaussdb array_remove function. + */ +public class GaussDBArrayRemoveFunction extends AbstractArrayRemoveFunction { + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); + final Expression indexExpression = (Expression) sqlAstArguments.get( 1 ); + + sqlAppender.append( "CASE WHEN "); + arrayExpression.accept( walker ); + sqlAppender.append( " IS NULL THEN NULL ELSE COALESCE(( SELECT array_agg(val) FROM unnest("); + arrayExpression.accept( walker ); + sqlAppender.append( ") AS val" ); + + if ( indexExpression instanceof Literal ) { + Literal literal = (Literal) indexExpression; + Object literalValue = literal.getLiteralValue(); + if ( literalValue != null ) { + appendWhere( sqlAppender, walker, indexExpression ); + } + else { + sqlAppender.append( " where val IS NOT NULL" ); + } + } + else { + appendWhere( sqlAppender, walker, indexExpression ); + } + sqlAppender.append( "), CAST(ARRAY[] AS VARCHAR[]) ) END AS result_array" ); + } + + /** + * can not get value if type like string + * @param sqlAppender + * @param walker + * @param indexExpression + */ + private static void appendWhere(SqlAppender sqlAppender, SqlAstTranslator walker, Expression indexExpression) { + sqlAppender.append( " where val IS NULL OR val not in (" ); + indexExpression.accept( walker ); + sqlAppender.append( ")" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayRemoveIndexFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayRemoveIndexFunction.java new file mode 100644 index 000000000000..60c081d047d3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayRemoveIndexFunction.java @@ -0,0 +1,67 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.Literal; + +import java.util.List; + +/** + * Gaussdb array_remove function. + */ +public class GaussDBArrayRemoveIndexFunction extends ArrayRemoveIndexUnnestFunction { + + + + public GaussDBArrayRemoveIndexFunction(boolean castEmptyArrayLiteral) { + super( castEmptyArrayLiteral ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); + final Expression indexExpression = (Expression) sqlAstArguments.get( 1 ); + + sqlAppender.append( "case when "); + arrayExpression.accept( walker ); + sqlAppender.append( " IS NOT NULL THEN COALESCE((SELECT array_agg(" ); + arrayExpression.accept( walker ); + sqlAppender.append( "[idx]) FROM generate_subscripts(" ); + arrayExpression.accept( walker ); + sqlAppender.append( ", 1) AS idx " ); + + if ( indexExpression instanceof Literal ) { + Literal literal = (Literal) indexExpression; + Object literalValue = literal.getLiteralValue(); + if ( literalValue != null ) { + appendWhere( sqlAppender, walker, indexExpression ); + } + } + else { + appendWhere( sqlAppender, walker, indexExpression ); + } + + sqlAppender.append( "), CAST(ARRAY[] AS VARCHAR ARRAY)) " ); + if ( castEmptyArrayLiteral ) { + sqlAppender.append( "ELSE CAST(ARRAY[] AS VARCHAR ARRAY) " ); + } + sqlAppender.append( "END AS result_array" ); + } + + private static void appendWhere(SqlAppender sqlAppender, SqlAstTranslator walker, Expression indexExpression) { + sqlAppender.append( "where idx not in (" ); + indexExpression.accept( walker ); + sqlAppender.append( ")" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayReplaceFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayReplaceFunction.java new file mode 100644 index 000000000000..e153e72b57b6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayReplaceFunction.java @@ -0,0 +1,53 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.Literal; + +import java.util.List; + +/** + * Gaussdb array_replace function. + */ +public class GaussDBArrayReplaceFunction extends ArrayReplaceUnnestFunction { + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + + sqlAppender.append( "CASE WHEN "); + sqlAstArguments.get( 0 ).accept( walker ); + sqlAppender.append( " IS NULL THEN NULL ELSE COALESCE((SELECT array_agg(CASE "); + final Expression originValueExpression = (Expression) sqlAstArguments.get( 1 ); + if ( originValueExpression instanceof Literal ) { + Literal literal = (Literal) originValueExpression; + Object literalValue = literal.getLiteralValue(); + if ( literalValue != null ) { + sqlAppender.append( "WHEN val = "); + sqlAstArguments.get( 1 ).accept( walker ); + } + else { + sqlAppender.append( "WHEN val is null "); + } + } + else { + sqlAppender.append( "WHEN val = "); + sqlAstArguments.get( 1 ).accept( walker ); + } + sqlAppender.append( " THEN "); + sqlAstArguments.get( 2 ).accept( walker ); + sqlAppender.append( " ELSE val END) FROM unnest( "); + sqlAstArguments.get( 0 ).accept( walker ); + sqlAppender.append( ") AS val ), CAST(ARRAY[] AS VARCHAR[]) ) END AS result_array"); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArraySetFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArraySetFunction.java new file mode 100644 index 000000000000..3daa6399af49 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArraySetFunction.java @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; +import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; +import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; + +import java.util.List; + +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.ANY; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; + +/** + * Gaussdb array_set function. + */ +public class GaussDBArraySetFunction extends AbstractSqmSelfRenderingFunctionDescriptor { + + public GaussDBArraySetFunction() { + super( + "array_set", + StandardArgumentsValidators.composite( + new ArrayAndElementArgumentValidator( 0, 2 ), + new ArgumentTypesValidator( null, ANY, INTEGER, ANY ) + ), + ArrayViaArgumentReturnTypeResolver.DEFAULT_INSTANCE, + StandardFunctionArgumentTypeResolvers.composite( + StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE, + StandardFunctionArgumentTypeResolvers.invariant( ANY, INTEGER, ANY ), + new ArrayAndElementArgumentTypeResolver( 0, 2 ) + ) + ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); + final Expression indexExpression = (Expression) sqlAstArguments.get( 1 ); + final Expression elementExpression = (Expression) sqlAstArguments.get( 2 ); + + sqlAppender.append( "( SELECT array_agg( CASE WHEN idx_gen = "); + indexExpression.accept( walker ); + sqlAppender.append( " THEN "); + elementExpression.accept( walker ); + sqlAppender.append( " ELSE CASE WHEN idx_gen <= array_length(ewa1_0.the_array, 1) "); + sqlAppender.append( " THEN ewa1_0.the_array[idx_gen] ELSE NULL END END ORDER BY idx_gen ) "); + sqlAppender.append( " FROM generate_series(1, GREATEST(COALESCE(array_length( "); + arrayExpression.accept( walker ); + sqlAppender.append( " , 1), 0), "); + indexExpression.accept( walker ); + sqlAppender.append( " )) AS idx_gen ) AS result_array "); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayTrimFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayTrimFunction.java new file mode 100644 index 000000000000..00b88437c64c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/GaussDBArrayTrimFunction.java @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.array; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; + +import java.util.List; + +/** + * Gaussdb array_trim function. + * + * Notes: Original code of this class is based on PostgreSQLArrayTrimEmulation. + */ +public class GaussDBArrayTrimFunction extends AbstractArrayTrimFunction { + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + + final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); + final Expression lengthExpression = (Expression) sqlAstArguments.get( 1 ); + + sqlAppender.append( "array_trim("); + arrayExpression.accept( walker ); + sqlAppender.append( ","); + lengthExpression.accept( walker ); + sqlAppender.append( ")"); + + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayAggFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayAggFunction.java new file mode 100644 index 000000000000..75bf0e8c893c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayAggFunction.java @@ -0,0 +1,63 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.Clause; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.predicate.Predicate; +import org.hibernate.sql.ast.tree.select.SortSpecification; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB json_arrayagg function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLJsonArrayAggFunction. + */ +public class GaussDBJsonArrayAggFunction extends JsonArrayAggFunction { + + private final boolean supportsStandard; + + public GaussDBJsonArrayAggFunction(boolean supportsStandard, TypeConfiguration typeConfiguration) { + super( true, typeConfiguration ); + this.supportsStandard = supportsStandard; + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + Predicate filter, + List withinGroup, + ReturnableType returnType, + SqlAstTranslator translator) { + + final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); + + sqlAppender.appendSql( "to_jsonb( array_agg( CASE WHEN " ); + arrayExpression.accept( translator ); + sqlAppender.appendSql( " IS NOT NULL THEN " ); + arrayExpression.accept( translator ); + sqlAppender.appendSql( "::text ELSE NULL END" ); + if ( withinGroup != null && !withinGroup.isEmpty() ) { + translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP ); + sqlAppender.appendSql( " order by " ); + withinGroup.get( 0 ).accept( translator ); + for ( int i = 1; i < withinGroup.size(); i++ ) { + sqlAppender.appendSql( ',' ); + withinGroup.get( i ).accept( translator ); + } + translator.getCurrentClauseStack().pop(); + } + sqlAppender.appendSql( ") ) AS result" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayAppendFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayAppendFunction.java new file mode 100644 index 000000000000..4eb0991551a2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayAppendFunction.java @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import java.util.List; + +import org.hibernate.metamodel.mapping.JdbcMappingContainer; +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB json_array_append function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLJsonArrayAppendFunction. + */ +public class GaussDBJsonArrayAppendFunction extends AbstractJsonArrayAppendFunction { + + private final boolean supportsLax; + + public GaussDBJsonArrayAppendFunction(boolean supportsLax, TypeConfiguration typeConfiguration) { + super( typeConfiguration ); + this.supportsLax = supportsLax; + } + + @Override + public void render( + SqlAppender sqlAppender, + List arguments, + ReturnableType returnType, + SqlAstTranslator translator) { + + + } + + private static boolean isJsonType(Expression expression) { + final JdbcMappingContainer expressionType = expression.getExpressionType(); + return expressionType != null && expressionType.getSingleJdbcMapping().getJdbcType().isJson(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayFunction.java new file mode 100644 index 000000000000..9a918b1946a6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayFunction.java @@ -0,0 +1,84 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; +import org.hibernate.query.sqm.function.FunctionKind; +import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.JsonNullBehavior; +import org.hibernate.sql.ast.tree.expression.Literal; +import org.hibernate.type.SqlTypes; +import org.hibernate.type.spi.TypeConfiguration; + +import java.util.List; + + +/** + * Notes: Original code of this class is based on JsonArrayFunction. + */ +public class GaussDBJsonArrayFunction extends AbstractSqmSelfRenderingFunctionDescriptor { + + public GaussDBJsonArrayFunction(TypeConfiguration typeConfiguration) { + super( + "json_array", + FunctionKind.NORMAL, + null, + StandardFunctionReturnTypeResolvers.invariant( + typeConfiguration.getBasicTypeRegistry().resolve( String.class, SqlTypes.JSON ) + ), + null + ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + sqlAppender.appendSql( "json_array" ); + char separator = '('; + if ( sqlAstArguments.isEmpty() ) { + sqlAppender.appendSql( separator ); + renderReturningClause( sqlAppender, walker ); + } + else { + final SqlAstNode lastArgument = sqlAstArguments.get( sqlAstArguments.size() - 1 ); + final JsonNullBehavior nullBehavior; + final int argumentsCount; + if ( lastArgument instanceof JsonNullBehavior ) { + nullBehavior = (JsonNullBehavior) lastArgument; + argumentsCount = sqlAstArguments.size() - 1; + } + else { + nullBehavior = JsonNullBehavior.ABSENT; + argumentsCount = sqlAstArguments.size(); + } + for ( int i = 0; i < argumentsCount; i++ ) { + Expression valueNode = (Expression) sqlAstArguments.get( i ); + if ( nullBehavior == JsonNullBehavior.ABSENT && valueNode instanceof Literal ) { + Object literalValue = ((Literal) valueNode).getLiteralValue(); + if ( literalValue == null ) { + continue; + } + } + sqlAppender.appendSql( separator ); + valueNode.accept( walker ); + separator = ','; + } + renderReturningClause( sqlAppender, walker ); + } + sqlAppender.appendSql( ')' ); + } + + protected void renderReturningClause(SqlAppender sqlAppender, SqlAstTranslator walker) { + // No-op + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayInsertFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayInsertFunction.java new file mode 100644 index 000000000000..dd9399e00750 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonArrayInsertFunction.java @@ -0,0 +1,48 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB json_array_insert function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLJsonArrayInsertFunction. + */ +public class GaussDBJsonArrayInsertFunction extends AbstractJsonArrayInsertFunction { + + public GaussDBJsonArrayInsertFunction(TypeConfiguration typeConfiguration) { + super( typeConfiguration ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List arguments, + ReturnableType returnType, + SqlAstTranslator translator) { + + final Expression json = (Expression) arguments.get( 0 ); + final Expression jsonPath = (Expression) arguments.get( 1 ); + final SqlAstNode value = arguments.get( 2 ); + + sqlAppender.append( "json_array_insert(" ); + json.accept( translator ); + sqlAppender.append( "," ); + jsonPath.accept( translator ); + sqlAppender.append( "," ); + value.accept( translator ); + sqlAppender.append( ")" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonInsertFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonInsertFunction.java new file mode 100644 index 000000000000..c15d4c1be072 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonInsertFunction.java @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB json_insert function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLJsonInsertFunction. + */ +public class GaussDBJsonInsertFunction extends AbstractJsonInsertFunction { + + public GaussDBJsonInsertFunction(TypeConfiguration typeConfiguration) { + super( typeConfiguration ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List arguments, + ReturnableType returnType, + SqlAstTranslator translator) { + + final Expression json = (Expression) arguments.get( 0 ); + final Expression jsonPath = (Expression) arguments.get( 1 ); + final SqlAstNode value = arguments.get( 2 ); + sqlAppender.appendSql( "json_insert(" ); + json.accept( translator ); + sqlAppender.appendSql( "," ); + jsonPath.accept( translator ); + sqlAppender.appendSql( "," ); + value.accept( translator ); + sqlAppender.appendSql( ")" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonMergepatchFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonMergepatchFunction.java new file mode 100644 index 000000000000..5e6db40072dd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonMergepatchFunction.java @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB json_mergepatch function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLJsonMergepatchFunction. + */ +public class GaussDBJsonMergepatchFunction extends AbstractJsonMergepatchFunction { + + public GaussDBJsonMergepatchFunction(TypeConfiguration typeConfiguration) { + super( typeConfiguration ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List arguments, + ReturnableType returnType, + SqlAstTranslator translator) { + + sqlAppender.appendSql( "json_merge" ); + char separator = '('; + for ( int i = 0; i < arguments.size(); i++ ) { + sqlAppender.appendSql( separator ); + arguments.get( i ).accept( translator ); + separator = ','; + } + sqlAppender.appendSql( ")" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonObjectAggFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonObjectAggFunction.java new file mode 100644 index 000000000000..2ad4ca528118 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonObjectAggFunction.java @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.predicate.Predicate; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB json_objectagg function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLJsonObjectAggFunction. + */ +public class GaussDBJsonObjectAggFunction extends JsonObjectAggFunction { + + + public GaussDBJsonObjectAggFunction(boolean supportsStandard, TypeConfiguration typeConfiguration) { + super( ":", true, typeConfiguration ); + } + + @Override + protected void render( + SqlAppender sqlAppender, + JsonObjectAggArguments arguments, + Predicate filter, + ReturnableType returnType, + SqlAstTranslator translator) { + + sqlAppender.appendSql( "json_object_agg(" ); + sqlAppender.appendSql( "CASE WHEN " ); + arguments.key().accept( translator ); + sqlAppender.appendSql( " IS NOT NULL " ); + sqlAppender.appendSql( " THEN " ); + arguments.key().accept( translator ); + sqlAppender.appendSql( " END," ); + arguments.value().accept( translator ); + sqlAppender.appendSql( ")" ); + } + + @Override + protected void renderUniqueAndReturningClause(SqlAppender sqlAppender, JsonObjectAggArguments arguments, SqlAstTranslator translator) { + renderUniqueClause( sqlAppender, arguments, translator ); + renderReturningClause( sqlAppender, arguments, translator ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonObjectFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonObjectFunction.java new file mode 100644 index 000000000000..cc5a75d2aa12 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonObjectFunction.java @@ -0,0 +1,73 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.JsonNullBehavior; +import org.hibernate.type.spi.TypeConfiguration; + +import java.util.List; + +/** + * Gaussdb json_object function. + * + * Notes: Original code of this class is based on PostgreSQLJsonObjectFunction. + */ +public class GaussDBJsonObjectFunction extends JsonObjectFunction { + + public GaussDBJsonObjectFunction(TypeConfiguration typeConfiguration) { + super( typeConfiguration, false ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + + sqlAppender.appendSql( "json_build_object" ); + char separator = '('; + if ( sqlAstArguments.isEmpty() ) { + sqlAppender.appendSql( separator ); + } + else { + final JsonNullBehavior nullBehavior; + final int argumentsCount; + if ( ( sqlAstArguments.size() & 1 ) == 1 ) { + nullBehavior = (JsonNullBehavior) sqlAstArguments.get( sqlAstArguments.size() - 1 ); + argumentsCount = sqlAstArguments.size() - 1; + } + else { + nullBehavior = JsonNullBehavior.NULL; + argumentsCount = sqlAstArguments.size(); + } + sqlAppender.appendSql('('); + separator = ' '; + for ( int i = 0; i < argumentsCount; i += 2 ) { + final SqlAstNode key = sqlAstArguments.get( i ); + Expression valueNode = (Expression) sqlAstArguments.get( i+1 ); + if ( nullBehavior == JsonNullBehavior.ABSENT && walker.getLiteralValue( valueNode ) == null) { + continue; + } + if (separator != ' ') { + sqlAppender.appendSql(separator); + } + else { + separator = ','; + } + key.accept( walker ); + sqlAppender.appendSql( ',' ); + valueNode.accept( walker ); + } + } + sqlAppender.appendSql( ')' ); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonRemoveFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonRemoveFunction.java new file mode 100644 index 000000000000..1dd82c67b24b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonRemoveFunction.java @@ -0,0 +1,50 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import java.util.List; + +import org.hibernate.metamodel.mapping.JdbcMappingContainer; +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB json_remove function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLJsonSetFunction. + */ +public class GaussDBJsonRemoveFunction extends AbstractJsonRemoveFunction { + + public GaussDBJsonRemoveFunction(TypeConfiguration typeConfiguration) { + super( typeConfiguration ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List arguments, + ReturnableType returnType, + SqlAstTranslator translator) { + + final Expression json = (Expression) arguments.get( 0 ); + final Expression jsonPath = (Expression) arguments.get( 1 ); + sqlAppender.appendSql( "json_remove(" ); + json.accept( translator ); + sqlAppender.appendSql( "," ); + jsonPath.accept( translator ); + sqlAppender.appendSql( ")" ); + } + + private boolean isJsonType(Expression expression) { + final JdbcMappingContainer expressionType = expression.getExpressionType(); + return expressionType != null && expressionType.getSingleJdbcMapping().getJdbcType().isJson(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonReplaceFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonReplaceFunction.java new file mode 100644 index 000000000000..11109fbb24a9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonReplaceFunction.java @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB json_replace function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLJsonSetFunction. + */ +public class GaussDBJsonReplaceFunction extends AbstractJsonReplaceFunction { + + public GaussDBJsonReplaceFunction(TypeConfiguration typeConfiguration) { + super( typeConfiguration ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List arguments, + ReturnableType returnType, + SqlAstTranslator translator) { + + final Expression json = (Expression) arguments.get( 0 ); + final Expression jsonPath = (Expression) arguments.get( 1 ); + final SqlAstNode value = arguments.get( 2 ); + sqlAppender.appendSql( "json_replace(" ); + json.accept( translator ); + sqlAppender.appendSql( "," ); + jsonPath.accept( translator ); + sqlAppender.appendSql( "," ); + value.accept( translator ); + sqlAppender.appendSql( ")" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonSetFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonSetFunction.java new file mode 100644 index 000000000000..cc481f992309 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonSetFunction.java @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB json_set function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLJsonSetFunction. + */ +public class GaussDBJsonSetFunction extends AbstractJsonSetFunction { + + public GaussDBJsonSetFunction(TypeConfiguration typeConfiguration) { + super( typeConfiguration ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List arguments, + ReturnableType returnType, + SqlAstTranslator translator) { + + final Expression json = (Expression) arguments.get( 0 ); + final Expression jsonPath = (Expression) arguments.get( 1 ); + final SqlAstNode value = arguments.get( 2 ); + sqlAppender.appendSql( "json_set(" ); + json.accept( translator ); + sqlAppender.appendSql( "," ); + jsonPath.accept( translator ); + sqlAppender.appendSql( "," ); + value.accept( translator ); + sqlAppender.appendSql( ")" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonValueFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonValueFunction.java new file mode 100644 index 000000000000..96de171d0750 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussDBJsonValueFunction.java @@ -0,0 +1,70 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import java.util.Iterator; +import java.util.Map; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause; +import org.hibernate.type.descriptor.jdbc.JsonHelper; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB json_value function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLJsonValueFunction. + */ +public class GaussDBJsonValueFunction extends JsonValueFunction { + + + public GaussDBJsonValueFunction(TypeConfiguration typeConfiguration) { + super( typeConfiguration, true, true ); + } + + @Override + protected void render( + SqlAppender sqlAppender, + JsonValueArguments arguments, + ReturnableType returnType, + SqlAstTranslator walker) { + + if (arguments.returningType() != null) { + sqlAppender.appendSql( "(" ); + } + arguments.jsonDocument().accept( walker ); + sqlAppender.appendSql( "::json #>> '{" ); + String literalValue = walker.getLiteralValue( arguments.jsonPath() ); + + final JsonPathPassingClause passingClause = arguments.passingClause(); + if ( passingClause != null ) { + final Map passingExpressions = passingClause.getPassingExpressions(); + final Iterator> iterator = passingExpressions.entrySet().iterator(); + Map.Entry entry = iterator.next(); + literalValue = literalValue.replace( "$"+entry.getKey(), walker.getLiteralValue( entry.getValue()).toString() ); + while ( iterator.hasNext() ) { + entry = iterator.next(); + sqlAppender.appendSql( ',' ); + literalValue = literalValue.replace( "$"+entry.getKey(), walker.getLiteralValue( entry.getValue()).toString() ); + } + } + + sqlAppender.append( JsonHelper.parseJsonPath( literalValue ) ); + sqlAppender.appendSql( "}'" ); + if (arguments.returningType() != null) { + sqlAppender.appendSql( ")::" ); + arguments.returningType().accept( walker ); + } + } + + @Override + protected void renderReturningClause(SqlAppender sqlAppender, JsonValueArguments arguments, SqlAstTranslator walker) { + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussdbJsonExistsFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussdbJsonExistsFunction.java new file mode 100644 index 000000000000..eb4ad574fed7 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussdbJsonExistsFunction.java @@ -0,0 +1,58 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause; +import org.hibernate.type.spi.TypeConfiguration; + +import java.util.Iterator; +import java.util.Map; + + +/** + * PostgreSQL json_query function. + */ +public class GaussdbJsonExistsFunction extends JsonExistsFunction { + + public GaussdbJsonExistsFunction(TypeConfiguration typeConfiguration, + boolean supportsJsonPathExpression, + boolean supportsJsonPathPassingClause) { + super(typeConfiguration, supportsJsonPathExpression, supportsJsonPathPassingClause); + } + + @Override + protected void render( + SqlAppender sqlAppender, + JsonExistsArguments arguments, + ReturnableType returnType, + SqlAstTranslator walker) { + + sqlAppender.appendSql( "json_contains_path(" ); + arguments.jsonDocument().accept( walker ); + sqlAppender.appendSql( ",'one', '" ); + + String literalValue = walker.getLiteralValue( arguments.jsonPath() ); + final JsonPathPassingClause passingClause = arguments.passingClause(); + if ( passingClause != null ) { + final Map passingExpressions = passingClause.getPassingExpressions(); + final Iterator> iterator = passingExpressions.entrySet().iterator(); + Map.Entry entry = iterator.next(); + literalValue = literalValue.replace( "$"+entry.getKey(), walker.getLiteralValue( entry.getValue()).toString() ); + while ( iterator.hasNext() ) { + entry = iterator.next(); + sqlAppender.appendSql( ',' ); + literalValue = literalValue.replace( "$"+entry.getKey(), walker.getLiteralValue( entry.getValue()).toString() ); + } + } + + sqlAppender.appendSql( literalValue ); + sqlAppender.appendSql( "') = 1" ); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussdbJsonQueryFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussdbJsonQueryFunction.java new file mode 100644 index 000000000000..5e27acb12c9a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/json/GaussdbJsonQueryFunction.java @@ -0,0 +1,62 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.json; + +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause; +import org.hibernate.sql.ast.tree.expression.JsonQueryWrapMode; +import org.hibernate.type.descriptor.jdbc.JsonHelper; +import org.hibernate.type.spi.TypeConfiguration; + +import java.util.Iterator; +import java.util.Map; + +/** + * PostgreSQL json_query function. + */ +public class GaussdbJsonQueryFunction extends JsonQueryFunction { + + public GaussdbJsonQueryFunction(TypeConfiguration typeConfiguration) { + super( typeConfiguration, true, true ); + } + + @Override + protected void render( + SqlAppender sqlAppender, + JsonQueryArguments arguments, + ReturnableType returnType, + SqlAstTranslator walker) { + + if ( arguments.wrapMode() == JsonQueryWrapMode.WITH_WRAPPER ) { + sqlAppender.appendSql( "json_build_array(" ); + } + arguments.jsonDocument().accept( walker ); + sqlAppender.appendSql( "::json #> '{" ); + String literalValue = walker.getLiteralValue( arguments.jsonPath() ); + + final JsonPathPassingClause passingClause = arguments.passingClause(); + if ( passingClause != null ) { + final Map passingExpressions = passingClause.getPassingExpressions(); + final Iterator> iterator = passingExpressions.entrySet().iterator(); + Map.Entry entry = iterator.next(); + literalValue = literalValue.replace( "$"+entry.getKey(), walker.getLiteralValue( entry.getValue()).toString() ); + while ( iterator.hasNext() ) { + entry = iterator.next(); + sqlAppender.appendSql( ',' ); + literalValue = literalValue.replace( "$"+entry.getKey(), walker.getLiteralValue( entry.getValue()).toString() ); + } + } + + sqlAppender.append( JsonHelper.parseJsonPath( literalValue ) ); + sqlAppender.appendSql( "}'" ); + if ( arguments.wrapMode() == JsonQueryWrapMode.WITH_WRAPPER ) { + sqlAppender.appendSql( ")" ); + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/GaussDBXmlQueryFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/GaussDBXmlQueryFunction.java new file mode 100644 index 000000000000..08f7aa9d3eca --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/GaussDBXmlQueryFunction.java @@ -0,0 +1,50 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.function.xml; + +import java.util.List; + +import org.hibernate.dialect.function.json.ExpressionTypeHelper; +import org.hibernate.metamodel.model.domain.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * GaussDB xmlquery function. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLXmlQueryFunction. + */ +public class GaussDBXmlQueryFunction extends XmlQueryFunction { + + public GaussDBXmlQueryFunction(TypeConfiguration typeConfiguration) { + super( false, typeConfiguration ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + final Expression xmlDocument = (Expression) sqlAstArguments.get( 1 ); + final boolean needsCast = !ExpressionTypeHelper.isXml( xmlDocument ); + sqlAppender.appendSql( "(select xmlagg(v) from unnest(xpath(" ); + sqlAstArguments.get( 0 ).accept( walker ); + sqlAppender.appendSql( ',' ); + if ( needsCast ) { + sqlAppender.appendSql( "cast(" ); + } + sqlAstArguments.get( 1 ).accept( walker ); + if ( needsCast ) { + sqlAppender.appendSql( " as xml)" ); + } + sqlAppender.appendSql( ")) t(v))" ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/identity/GaussDBIdentityColumnSupport.java b/hibernate-core/src/main/java/org/hibernate/dialect/identity/GaussDBIdentityColumnSupport.java new file mode 100644 index 000000000000..2703ef8244d6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/identity/GaussDBIdentityColumnSupport.java @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.identity; + +import static org.hibernate.internal.util.StringHelper.unquote; + +/** + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLIdentityColumnSupport. + */ +public class GaussDBIdentityColumnSupport extends IdentityColumnSupportImpl { + + public static final GaussDBIdentityColumnSupport INSTANCE = new GaussDBIdentityColumnSupport(); + @Override + public boolean supportsIdentityColumns() { + return true; + } + + @Override + public String getIdentitySelectString(String table, String column, int type) { + return "select currval('" + unquote(table) + '_' + unquote(column) + "_seq')"; + } + + @Override + public String getIdentityColumnString(int type) { + return "generated by default as identity"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/sequence/GaussDBSequenceSupport.java b/hibernate-core/src/main/java/org/hibernate/dialect/sequence/GaussDBSequenceSupport.java new file mode 100644 index 000000000000..9b97eaf0b70b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/sequence/GaussDBSequenceSupport.java @@ -0,0 +1,41 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.dialect.sequence; + +import org.hibernate.MappingException; +import org.hibernate.dialect.GaussDBDialect; + +/** + * Sequence support for {@link GaussDBDialect}. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLAggregateSupport. + */ +public class GaussDBSequenceSupport implements SequenceSupport { + + public static final SequenceSupport INSTANCE = new GaussDBSequenceSupport(); + + @Override + public String getSelectSequenceNextValString(String sequenceName) { + return "nextval('" + sequenceName + "')"; + } + + @Override + public String getSelectSequencePreviousValString(String sequenceName) throws MappingException { + return "currval('" + sequenceName + "')"; + } + + @Override + public boolean sometimesNeedsStartingValue() { + return true; + } + + @Override + public String getDropSequenceString(String sequenceName) { + return "drop sequence if exists " + sequenceName; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/GaussDBCallableStatementSupport.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/GaussDBCallableStatementSupport.java new file mode 100644 index 000000000000..b7e2818dbc0a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/GaussDBCallableStatementSupport.java @@ -0,0 +1,184 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.procedure.internal; + +import java.util.List; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.AbstractGaussDBStructJdbcType; +import org.hibernate.procedure.spi.FunctionReturnImplementor; +import org.hibernate.procedure.spi.ProcedureCallImplementor; +import org.hibernate.procedure.spi.ProcedureParameterImplementor; +import org.hibernate.query.OutputableType; +import org.hibernate.query.spi.ProcedureParameterMetadataImplementor; +import org.hibernate.sql.exec.internal.JdbcCallImpl; +import org.hibernate.sql.exec.spi.JdbcCallParameterRegistration; +import org.hibernate.sql.exec.spi.JdbcOperationQueryCall; +import org.hibernate.type.SqlTypes; + +import jakarta.persistence.ParameterMode; + +/** + * GaussDB implementation of CallableStatementSupport. + * + * @author liubao + * + * Notes: Original code of this class is based on PostgreSQLTruncFunction. + */ +public class GaussDBCallableStatementSupport extends AbstractStandardCallableStatementSupport { + /** + * Singleton access + */ + public static final GaussDBCallableStatementSupport INSTANCE = new GaussDBCallableStatementSupport( true ); + public static final GaussDBCallableStatementSupport V10_INSTANCE = new GaussDBCallableStatementSupport( false ); + + private final boolean supportsProcedures; + + private GaussDBCallableStatementSupport(boolean supportsProcedures) { + this.supportsProcedures = supportsProcedures; + } + + @Override + public JdbcOperationQueryCall interpretCall(ProcedureCallImplementor procedureCall) { + final String procedureName = procedureCall.getProcedureName(); + final FunctionReturnImplementor functionReturn = procedureCall.getFunctionReturn(); + final ProcedureParameterMetadataImplementor parameterMetadata = procedureCall.getParameterMetadata(); + final boolean firstParamIsRefCursor = parameterMetadata.getParameterCount() != 0 + && isFirstParameterModeRefCursor( parameterMetadata ); + + final List> registrations = parameterMetadata.getRegistrationsAsList(); + final int paramStringSizeEstimate; + if ( functionReturn == null && parameterMetadata.hasNamedParameters() ) { + // That's just a rough estimate. I guess most params will have fewer than 8 chars on average + paramStringSizeEstimate = registrations.size() * 10; + } + else { + // For every param rendered as '?' we have a comma, hence the estimate + paramStringSizeEstimate = registrations.size() * 2; + } + final JdbcCallImpl.Builder builder = new JdbcCallImpl.Builder(); + + final int jdbcParameterOffset; + final int startIndex; + final CallMode callMode; + if ( functionReturn != null ) { + if ( functionReturn.getJdbcTypeCode() == SqlTypes.REF_CURSOR ) { + if ( firstParamIsRefCursor ) { + // validate that the parameter strategy is positional (cannot mix, and REF_CURSOR is inherently positional) + if ( parameterMetadata.hasNamedParameters() ) { + throw new HibernateException( "Cannot mix named parameters and REF_CURSOR parameter on GaussDB" ); + } + callMode = CallMode.CALL_RETURN; + startIndex = 1; + jdbcParameterOffset = 1; + builder.addParameterRegistration( registrations.get( 0 ).toJdbcParameterRegistration( 1, procedureCall ) ); + } + else { + callMode = CallMode.TABLE_FUNCTION; + startIndex = 0; + jdbcParameterOffset = 1; + // Old style +// callMode = CallMode.CALL_RETURN; +// startIndex = 0; +// jdbcParameterOffset = 2; +// builder.setFunctionReturn( functionReturn.toJdbcFunctionReturn( procedureCall.getSession() ) ); + } + } + else { + callMode = CallMode.FUNCTION; + startIndex = 0; + jdbcParameterOffset = 1; + } + } + else if ( supportsProcedures ) { + jdbcParameterOffset = 1; + startIndex = 0; + callMode = CallMode.NATIVE_CALL; + } + else if ( firstParamIsRefCursor ) { + // validate that the parameter strategy is positional (cannot mix, and REF_CURSOR is inherently positional) + if ( parameterMetadata.hasNamedParameters() ) { + throw new HibernateException( "Cannot mix named parameters and REF_CURSOR parameter on GaussDB" ); + } + jdbcParameterOffset = 1; + startIndex = 1; + callMode = CallMode.CALL_RETURN; + builder.addParameterRegistration( registrations.get( 0 ).toJdbcParameterRegistration( 1, procedureCall ) ); + } + else { + jdbcParameterOffset = 1; + startIndex = 0; + callMode = CallMode.CALL; + } + + final StringBuilder buffer = new StringBuilder( callMode.start.length() + callMode.end.length() + procedureName.length() + paramStringSizeEstimate ) + .append( callMode.start ); + buffer.append( procedureName ); + + if ( startIndex == registrations.size() ) { + buffer.append( '(' ); + } + else { + char sep = '('; + for ( int i = startIndex; i < registrations.size(); i++ ) { + final ProcedureParameterImplementor parameter = registrations.get( i ); + if ( !supportsProcedures && parameter.getMode() == ParameterMode.REF_CURSOR ) { + throw new HibernateException( + "GaussDB supports only one REF_CURSOR parameter, but multiple were registered" ); + } + buffer.append( sep ); + final JdbcCallParameterRegistration registration = parameter.toJdbcParameterRegistration( + i + jdbcParameterOffset, + procedureCall + ); + final OutputableType type = registration.getParameterType(); + final String castType; + if ( parameter.getName() != null ) { + buffer.append( parameter.getName() ).append( " => " ); + } + if ( type != null && type.getJdbcType() instanceof AbstractGaussDBStructJdbcType ) { + // We have to cast struct type parameters so that GaussDB understands nulls + castType = ( (AbstractGaussDBStructJdbcType) type.getJdbcType() ).getStructTypeName(); + buffer.append( "cast(" ); + } + else { + castType = null; + } + buffer.append( "?" ); + if ( castType != null ) { + buffer.append( " as " ).append( castType ).append( ')' ); + } + sep = ','; + builder.addParameterRegistration( registration ); + } + } + + buffer.append( callMode.end ); + builder.setCallableName( buffer.toString() ); + return builder.buildJdbcCall(); + } + + private static boolean isFirstParameterModeRefCursor(ProcedureParameterMetadataImplementor parameterMetadata) { + return parameterMetadata.getRegistrationsAsList().get( 0 ).getMode() == ParameterMode.REF_CURSOR; + } + + enum CallMode { + TABLE_FUNCTION("select * from ", ")"), + FUNCTION("select ", ")"), + NATIVE_CALL("call ", ")"), + CALL_RETURN("{?=call ", ")}"), + CALL("{call ", ")}"); + + private final String start; + private final String end; + + CallMode(String start, String end) { + this.start = start; + this.end = end; + } + + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/SqlAstWalker.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/SqlAstWalker.java index c596ea03eac7..c63bab9e1309 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/SqlAstWalker.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/SqlAstWalker.java @@ -59,6 +59,7 @@ import org.hibernate.sql.ast.tree.predicate.InListPredicate; import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate; import org.hibernate.sql.ast.tree.predicate.Junction; +import org.hibernate.sql.ast.tree.predicate.LessThanPredicate; import org.hibernate.sql.ast.tree.predicate.LikePredicate; import org.hibernate.sql.ast.tree.predicate.NegatedPredicate; import org.hibernate.sql.ast.tree.predicate.NullnessPredicate; @@ -187,6 +188,7 @@ public interface SqlAstWalker { void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate); void visitBetweenPredicate(BetweenPredicate betweenPredicate); + void visitLessThanPredicate(LessThanPredicate lessThanPredicate); void visitFilterPredicate(FilterPredicate filterPredicate); void visitFilterFragmentPredicate(FilterPredicate.FilterFragmentPredicate fragmentPredicate); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java index d140524d8bd0..abc5089df9eb 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java @@ -172,6 +172,7 @@ import org.hibernate.sql.ast.tree.predicate.InListPredicate; import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate; import org.hibernate.sql.ast.tree.predicate.Junction; +import org.hibernate.sql.ast.tree.predicate.LessThanPredicate; import org.hibernate.sql.ast.tree.predicate.LikePredicate; import org.hibernate.sql.ast.tree.predicate.NegatedPredicate; import org.hibernate.sql.ast.tree.predicate.NullnessPredicate; @@ -7545,6 +7546,14 @@ public void visitBetweenPredicate(BetweenPredicate betweenPredicate) { betweenPredicate.getUpperBound().accept( this ); } + @Override + public void visitLessThanPredicate(LessThanPredicate lessThanPredicate) { + + lessThanPredicate.getExpression().accept( this ); + appendSql( " < " ); + lessThanPredicate.getUpperBound().accept( this ); + } + @Override public void visitFilterPredicate(FilterPredicate filterPredicate) { // visits each fragment with " and " between them diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstWalker.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstWalker.java index ceefcf50c63d..28311b3a0aae 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstWalker.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstWalker.java @@ -65,6 +65,7 @@ import org.hibernate.sql.ast.tree.predicate.InListPredicate; import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate; import org.hibernate.sql.ast.tree.predicate.Junction; +import org.hibernate.sql.ast.tree.predicate.LessThanPredicate; import org.hibernate.sql.ast.tree.predicate.LikePredicate; import org.hibernate.sql.ast.tree.predicate.NegatedPredicate; import org.hibernate.sql.ast.tree.predicate.NullnessPredicate; @@ -603,4 +604,10 @@ public void visitStandardTableDelete(TableDeleteStandard tableDelete) { public void visitCustomTableDelete(TableDeleteCustomSql tableDelete) { throw new UnsupportedOperationException(); } + + @Override + public void visitLessThanPredicate(LessThanPredicate lessThanPredicate) { + + throw new UnsupportedOperationException(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/ExpressionReplacementWalker.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/ExpressionReplacementWalker.java index 49572a3f1870..72993c01e08c 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/ExpressionReplacementWalker.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/ExpressionReplacementWalker.java @@ -63,6 +63,7 @@ import org.hibernate.sql.ast.tree.predicate.InListPredicate; import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate; import org.hibernate.sql.ast.tree.predicate.Junction; +import org.hibernate.sql.ast.tree.predicate.LessThanPredicate; import org.hibernate.sql.ast.tree.predicate.LikePredicate; import org.hibernate.sql.ast.tree.predicate.NegatedPredicate; import org.hibernate.sql.ast.tree.predicate.NullnessPredicate; @@ -650,4 +651,10 @@ public void visitCustomTableDelete(TableDeleteCustomSql tableDelete) { public void visitColumnWriteFragment(ColumnWriteFragment columnWriteFragment) { throw new UnsupportedOperationException(); } + + @Override + public void visitLessThanPredicate(LessThanPredicate lessThanPredicate) { + + throw new UnsupportedOperationException(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/predicate/LessThanPredicate.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/predicate/LessThanPredicate.java new file mode 100644 index 000000000000..cb243abbd2ea --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/predicate/LessThanPredicate.java @@ -0,0 +1,41 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.sql.ast.tree.predicate; + +import org.hibernate.metamodel.mapping.JdbcMappingContainer; +import org.hibernate.sql.ast.SqlAstWalker; +import org.hibernate.sql.ast.tree.expression.Expression; + +/** + * @author Steve Ebersole + */ +public class LessThanPredicate extends AbstractPredicate { + + private final Expression expression; + private final Expression upperBound; + + public LessThanPredicate( + Expression expression, + Expression upperBound, + boolean negated, + JdbcMappingContainer expressionType) { + super( expressionType, negated ); + this.expression = expression; + this.upperBound = upperBound; + } + + public Expression getExpression() { + return expression; + } + + public Expression getUpperBound() { + return upperBound; + } + + @Override + public void accept(SqlAstWalker sqlTreeWalker) { + sqlTreeWalker.visitLessThanPredicate( this ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java index e6bd54878626..94e43b7f989c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java @@ -11,9 +11,11 @@ import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.util.AbstractCollection; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; +import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; @@ -1624,4 +1626,30 @@ public T[] toArray(T[] a) { } } + public static String parseJsonPath(String path) { + if (path == null || !path.startsWith("$")) { + throw new IllegalArgumentException("Invalid JSON path"); + } + + List result = new ArrayList<>(); + String[] parts = path.substring(1).split("\\."); + + for (String part : parts) { + while (part.contains("[")) { + int start = part.indexOf("["); + int end = part.indexOf("]", start); + if (end == -1) { + throw new IllegalArgumentException("Invalid JSON path format"); + } + result.add(part.substring(0, start)); + result.add(part.substring(start + 1, end)); + part = part.substring(end + 1); + } + if (!part.isEmpty()) { + result.add(part); + } + } + + return String.join(",", result); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/event/service/internal/NewlyInstantiatdCollectionSkipDeleteOrphanTest.java b/hibernate-core/src/test/java/org/hibernate/event/service/internal/NewlyInstantiatdCollectionSkipDeleteOrphanTest.java index 8cd3a29658f7..519ce4c94378 100644 --- a/hibernate-core/src/test/java/org/hibernate/event/service/internal/NewlyInstantiatdCollectionSkipDeleteOrphanTest.java +++ b/hibernate-core/src/test/java/org/hibernate/event/service/internal/NewlyInstantiatdCollectionSkipDeleteOrphanTest.java @@ -10,38 +10,41 @@ import java.util.HashSet; import java.util.Objects; import java.util.Set; -import jakarta.persistence.Column; -import jakarta.persistence.Embeddable; -import jakarta.persistence.EmbeddedId; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.MapsId; -import jakarta.persistence.OneToMany; -import jakarta.persistence.Table; -import jakarta.persistence.Transient; -import jakarta.persistence.Version; import org.hibernate.FlushMode; import org.hibernate.Transaction; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.dialect.GaussDBDialect; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapsId; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; +import jakarta.persistence.Version; + import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -102,6 +105,7 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void VersionedMappingVersionedParentSaveUpdate(SessionFactoryScope scope) { scope.inSession( s -> { s.setHibernateFlushMode( FlushMode.MANUAL ); @@ -143,6 +147,7 @@ public void VersionedMappingVersionedParentSaveUpdate(SessionFactoryScope scope) } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void VersionedMappingUnversionedParentSaveUpdate(SessionFactoryScope scope) { scope.inSession( s -> { s.setHibernateFlushMode( FlushMode.MANUAL ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/circle/identity/CascadeCircleIdentityIdTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/circle/identity/CascadeCircleIdentityIdTest.java index d12927f83356..c053e8b24148 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/circle/identity/CascadeCircleIdentityIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/circle/identity/CascadeCircleIdentityIdTest.java @@ -4,12 +4,15 @@ */ package org.hibernate.orm.test.annotations.cascade.circle.identity; -import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.Test; @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) @@ -30,6 +33,7 @@ public class CascadeCircleIdentityIdTest { @Test @JiraKey(value = "HHH-5472") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testCascade(SessionFactoryScope scope) { A a = new A(); B b = new B(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/multicircle/jpa/identity/MultiCircleJpaCascadeIdentityTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/multicircle/jpa/identity/MultiCircleJpaCascadeIdentityTest.java index 3c85a5090ed8..ebdab785a759 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/multicircle/jpa/identity/MultiCircleJpaCascadeIdentityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/multicircle/jpa/identity/MultiCircleJpaCascadeIdentityTest.java @@ -4,11 +4,14 @@ */ package org.hibernate.orm.test.annotations.cascade.multicircle.jpa.identity; +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -64,7 +67,7 @@ * Entities are inserted in the following order: * c, e, d, b, g, f. */ -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) @DomainModel( annotatedClasses = { EntityB.class, @@ -158,6 +161,7 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testPersist(SessionFactoryScope scope) { scope.inTransaction( session -> session.persist( b ) @@ -167,6 +171,7 @@ public void testPersist(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testMerge(SessionFactoryScope scope) { scope.inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/multicircle/nonjpa/identity/MultiCircleNonJpaCascadeIdentityTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/multicircle/nonjpa/identity/MultiCircleNonJpaCascadeIdentityTest.java index b14884616de0..66964cf61656 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/multicircle/nonjpa/identity/MultiCircleNonJpaCascadeIdentityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/cascade/multicircle/nonjpa/identity/MultiCircleNonJpaCascadeIdentityTest.java @@ -5,11 +5,14 @@ package org.hibernate.orm.test.annotations.cascade.multicircle.nonjpa.identity; +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -160,6 +163,7 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testPersist(SessionFactoryScope scope) { scope.inTransaction( session -> session.persist( b ) @@ -169,6 +173,7 @@ public void testPersist(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testMerge(SessionFactoryScope scope) { scope.inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/ElementCollectionOfEmbeddableWithEntityWithEntityCollectionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/ElementCollectionOfEmbeddableWithEntityWithEntityCollectionTest.java index 689e5de9a2c1..a7a24e0cafc1 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/ElementCollectionOfEmbeddableWithEntityWithEntityCollectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/collectionelement/ElementCollectionOfEmbeddableWithEntityWithEntityCollectionTest.java @@ -4,35 +4,35 @@ */ package org.hibernate.orm.test.annotations.collectionelement; -import java.util.ArrayList; -import java.util.List; - +import jakarta.persistence.CollectionTable; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OrderColumn; +import jakarta.persistence.Table; +import org.assertj.core.api.Assertions; import org.hibernate.Hibernate; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.Fetch; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.orm.test.annotations.collectionelement.ElementCollectionOfEmbeddableWithEntityWithEntityCollectionTest.Event; import org.hibernate.orm.test.annotations.collectionelement.ElementCollectionOfEmbeddableWithEntityWithEntityCollectionTest.Plan; import org.hibernate.orm.test.annotations.collectionelement.ElementCollectionOfEmbeddableWithEntityWithEntityCollectionTest.SubPlan; - -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.jdbc.SQLStatementInspector; import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; 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.BeforeEach; import org.junit.jupiter.api.Test; -import jakarta.persistence.CollectionTable; -import jakarta.persistence.ElementCollection; -import jakarta.persistence.Embeddable; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToMany; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OrderColumn; -import jakarta.persistence.Table; -import org.assertj.core.api.Assertions; +import java.util.ArrayList; +import java.util.List; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.hibernate.annotations.CascadeType.ALL; @@ -80,6 +80,9 @@ public void setUp(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, + reason = "type:resolved.If you operate a table with the same name as the system view under the schema, " + + "you will be redirected to the system view and an error will be reported.") public void testInitializeCollection(SessionFactoryScope scope) { final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector(); statementInspector.clear(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/dataTypes/BasicOperationsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/dataTypes/BasicOperationsTest.java index c44f6e4fef0b..ee955dcd05a3 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/dataTypes/BasicOperationsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/dataTypes/BasicOperationsTest.java @@ -14,6 +14,8 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.community.dialect.AltibaseDialect; +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.PostgresPlusDialect; import org.hibernate.dialect.SybaseASEDialect; @@ -64,7 +66,11 @@ public void testCreateAndDelete(SessionFactoryScope scope) { scope.inTransaction( session -> { - session.doWork( new ValidateSomeEntityColumns( session ) ); + + Dialect dialect = session.getJdbcServices().getDialect(); + if ( !(dialect instanceof GaussDBDialect ) ) { + session.doWork( new ValidateSomeEntityColumns( session ) ); + } session.doWork( new ValidateRowCount( session, SOME_ENTITY_TABLE_NAME, 0 ) ); session.doWork( new ValidateRowCount( session, SOME_OTHER_ENTITY_TABLE_NAME, 0 ) ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/AbstractLobTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/AbstractLobTest.java index 06de2db391a9..0ebc6219d03c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/AbstractLobTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/AbstractLobTest.java @@ -4,11 +4,12 @@ */ package org.hibernate.orm.test.annotations.lob; -import org.hibernate.dialect.*; -import org.junit.Test; +import org.hibernate.dialect.GaussDBDialect; +import org.hibernate.dialect.SybaseDialect; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; import static org.junit.Assert.assertEquals; @@ -41,7 +42,10 @@ protected C createCompiledCode() { return getCompiledCodeClass().newInstance(); } catch (Exception ex) { - throw new RuntimeException( "Could not create an instance of type " + getCompiledCodeClass().getName(), ex ); + throw new RuntimeException( + "Could not create an instance of type " + getCompiledCodeClass().getName(), + ex + ); } } @@ -55,21 +59,27 @@ public void testSerializableToBlob() throws Exception { book.setEditor( editor ); book.setCode2( new char[] { 'r' } ); - doInHibernate( this::sessionFactory, session -> { - session.persist( book ); - } ); - - doInHibernate( this::sessionFactory, session -> { - B loadedBook = getBookClass().cast( session.get( getBookClass(), getId( book ) ) ); - assertNotNull( loadedBook.getEditor() ); - assertEquals( book.getEditor().getName(), loadedBook.getEditor().getName() ); - loadedBook.setEditor( null ); - } ); - - doInHibernate( this::sessionFactory, session -> { - B loadedBook = getBookClass().cast( session.get( getBookClass(), getId( book ) ) ); - assertNull( loadedBook.getEditor() ); - } ); + doInHibernate( + this::sessionFactory, session -> { + session.persist( book ); + } + ); + + doInHibernate( + this::sessionFactory, session -> { + B loadedBook = getBookClass().cast( session.get( getBookClass(), getId( book ) ) ); + assertNotNull( loadedBook.getEditor() ); + assertEquals( book.getEditor().getName(), loadedBook.getEditor().getName() ); + loadedBook.setEditor( null ); + } + ); + + doInHibernate( + this::sessionFactory, session -> { + B loadedBook = getBookClass().cast( session.get( getBookClass(), getId( book ) ) ); + assertNull( loadedBook.getEditor() ); + } + ); } @Test @@ -81,62 +91,75 @@ public void testClob() throws Exception { book.setCode( new Character[] { 'a', 'b', 'c' } ); book.setCode2( new char[] { 'a', 'b', 'c' } ); - doInHibernate( this::sessionFactory, session -> { - session.persist( book ); - } ); - - doInHibernate( this::sessionFactory, session -> { - B b2 = getBookClass().cast( session.get( getBookClass(), getId( book ) ) ); - assertNotNull( b2 ); - assertEquals( b2.getFullText(), book.getFullText() ); - assertEquals( b2.getCode()[1].charValue(), book.getCode()[1].charValue() ); - assertEquals( b2.getCode2()[2], book.getCode2()[2] ); - } ); + doInHibernate( + this::sessionFactory, session -> { + session.persist( book ); + } + ); + + doInHibernate( + this::sessionFactory, session -> { + B b2 = getBookClass().cast( session.get( getBookClass(), getId( book ) ) ); + assertNotNull( b2 ); + assertEquals( b2.getFullText(), book.getFullText() ); + assertEquals( b2.getCode()[1].charValue(), book.getCode()[1].charValue() ); + assertEquals( b2.getCode2()[2], book.getCode2()[2] ); + } + ); } @Test + @org.hibernate.testing.orm.junit.SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testBlob() throws Exception { C cc = createCompiledCode(); Byte[] header = new Byte[2]; - header[0] = new Byte( ( byte ) 3 ); - header[1] = new Byte( ( byte ) 0 ); + header[0] = new Byte( (byte) 3 ); + header[1] = new Byte( (byte) 0 ); cc.setHeader( header ); int codeSize = 5; byte[] full = new byte[codeSize]; for ( int i = 0; i < codeSize; i++ ) { - full[i] = ( byte ) ( 1 + i ); + full[i] = (byte) ( 1 + i ); } cc.setFullCode( full ); - doInHibernate( this::sessionFactory, session -> { - session.persist( cc ); - } ); - - doInHibernate( this::sessionFactory, session -> { - C recompiled = getCompiledCodeClass().cast( session.get( getCompiledCodeClass(), getId( cc ) ) ); - assertEquals( recompiled.getHeader()[1], cc.getHeader()[1] ); - assertEquals( recompiled.getFullCode()[codeSize - 1], cc.getFullCode()[codeSize - 1] ); - } ); + doInHibernate( + this::sessionFactory, session -> { + session.persist( cc ); + } + ); + + doInHibernate( + this::sessionFactory, session -> { + C recompiled = getCompiledCodeClass().cast( session.get( getCompiledCodeClass(), getId( cc ) ) ); + assertEquals( recompiled.getHeader()[1], cc.getHeader()[1] ); + assertEquals( recompiled.getFullCode()[codeSize - 1], cc.getFullCode()[codeSize - 1] ); + } + ); } @Test - @SkipForDialect( SybaseDialect.class ) + @SkipForDialect(SybaseDialect.class) public void testBinary() throws Exception { C cc = createCompiledCode(); byte[] metadata = new byte[2]; - metadata[0] = ( byte ) 3; - metadata[1] = ( byte ) 0; + metadata[0] = (byte) 3; + metadata[1] = (byte) 0; cc.setMetadata( metadata ); - doInHibernate( this::sessionFactory, session -> { - session.persist( cc ); - } ); - - doInHibernate( this::sessionFactory, session -> { - C recompiled = getCompiledCodeClass().cast( session.get( getCompiledCodeClass(), getId( cc ) ) ); - assertEquals( recompiled.getMetadata()[1], cc.getMetadata()[1] ); - } ); + doInHibernate( + this::sessionFactory, session -> { + session.persist( cc ); + } + ); + + doInHibernate( + this::sessionFactory, session -> { + C recompiled = getCompiledCodeClass().cast( session.get( getCompiledCodeClass(), getId( cc ) ) ); + assertEquals( recompiled.getMetadata()[1], cc.getMetadata()[1] ); + } + ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/MaterializedBlobTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/MaterializedBlobTest.java index e517a10b36e7..8260753fa366 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/MaterializedBlobTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/MaterializedBlobTest.java @@ -8,6 +8,7 @@ import org.hibernate.Session; import org.hibernate.dialect.CockroachDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.BasicValuedModelPart; import org.hibernate.metamodel.mapping.JdbcMapping; @@ -48,6 +49,7 @@ public void testTypeSelection() { } @Test + @org.hibernate.testing.orm.junit.SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSaving() { byte[] testData = "test data".getBytes(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/VersionedLobTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/VersionedLobTest.java index dc7f52e86f8f..f64d237b8c1c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/VersionedLobTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/lob/VersionedLobTest.java @@ -4,13 +4,15 @@ */ package org.hibernate.orm.test.annotations.lob; -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.SkipForDialect; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -127,7 +129,7 @@ public void testVersionUnchangedString() throws Exception { } @Test - @JiraKey( value = "HHH-5811") + @JiraKey(value = "HHH-5811") public void testVersionUnchangedByteArray() throws Exception { Session s; Transaction tx; @@ -135,8 +137,8 @@ public void testVersionUnchangedByteArray() throws Exception { tx = s.beginTransaction(); VersionedCompiledCode cc = createCompiledCode(); Byte[] header = new Byte[2]; - header[0] = new Byte( ( byte ) 3 ); - header[1] = new Byte( ( byte ) 0 ); + header[0] = new Byte( (byte) 3 ); + header[1] = new Byte( (byte) 0 ); cc.setHeader( header ); s.persist( cc ); tx.commit(); @@ -154,6 +156,7 @@ public void testVersionUnchangedByteArray() throws Exception { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testVersionUnchangedPrimitiveByteArray() throws Exception { Session s; Transaction tx; @@ -163,7 +166,7 @@ public void testVersionUnchangedPrimitiveByteArray() throws Exception { int codeSize = 5; byte[] full = new byte[codeSize]; for ( int i = 0; i < codeSize; i++ ) { - full[i] = ( byte ) ( 1 + i ); + full[i] = (byte) ( 1 + i ); } cc.setFullCode( full ); s.persist( cc ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/ManyToOneMapsIdFlushModeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/ManyToOneMapsIdFlushModeTest.java index 12c5f1bafdbc..0c4fa65e846e 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/ManyToOneMapsIdFlushModeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/ManyToOneMapsIdFlushModeTest.java @@ -7,6 +7,16 @@ import java.util.HashSet; import java.util.Set; +import org.hibernate.dialect.GaussDBDialect; +import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; + +import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.SkipForDialect; +import org.hibernate.testing.transaction.TransactionUtil; +import org.junit.Test; + import jakarta.persistence.Entity; import jakarta.persistence.FlushModeType; import jakarta.persistence.GeneratedValue; @@ -16,14 +26,6 @@ import jakarta.persistence.MapsId; import jakarta.persistence.OneToMany; -import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; -import org.junit.Test; - -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.RequiresDialectFeature; -import org.hibernate.testing.orm.junit.JiraKey; -import org.hibernate.testing.transaction.TransactionUtil; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -40,32 +42,37 @@ protected Class[] getAnnotatedClasses() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testFlushModeCommitWithMapsIdAndIdentity() { - final ParentEntity parent = TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> { - entityManager.setFlushMode( FlushModeType.COMMIT ); - - final ParentEntity parentEntity = new ParentEntity(); - parentEntity.setData( "test" ); - - final ChildEntity childEntity = new ChildEntity(); - parentEntity.addChild( childEntity ); - - entityManager.persist( parentEntity ); - entityManager.persist( childEntity ); - - return parentEntity; - } ); - - TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> { - final ParentEntity parentEntity = entityManager.find( ParentEntity.class, parent.getId() ); - assertNotNull( parentEntity ); - assertNotNull( parentEntity.getChildren() ); - assertTrue( !parentEntity.getChildren().isEmpty() ); - - final ChildEntity childEntity = parentEntity.getChildren().iterator().next(); - assertNotNull( childEntity ); - assertEquals( parentEntity.getId(), childEntity.getId() ); - } ); + final ParentEntity parent = TransactionUtil.doInJPA( + this::entityManagerFactory, entityManager -> { + entityManager.setFlushMode( FlushModeType.COMMIT ); + + final ParentEntity parentEntity = new ParentEntity(); + parentEntity.setData( "test" ); + + final ChildEntity childEntity = new ChildEntity(); + parentEntity.addChild( childEntity ); + + entityManager.persist( parentEntity ); + entityManager.persist( childEntity ); + + return parentEntity; + } + ); + + TransactionUtil.doInJPA( + this::entityManagerFactory, entityManager -> { + final ParentEntity parentEntity = entityManager.find( ParentEntity.class, parent.getId() ); + assertNotNull( parentEntity ); + assertNotNull( parentEntity.getChildren() ); + assertTrue( !parentEntity.getChildren().isEmpty() ); + + final ChildEntity childEntity = parentEntity.getChildren().iterator().next(); + assertNotNull( childEntity ); + assertEquals( parentEntity.getId(), childEntity.getId() ); + } + ); } @Entity(name = "ParentEntity") diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/NotNullManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/NotNullManyToOneTest.java index 7560022f28b6..1178e87b4192 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/NotNullManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/NotNullManyToOneTest.java @@ -7,11 +7,13 @@ import org.hibernate.boot.beanvalidation.ValidationMode; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.Test; import jakarta.persistence.CascadeType; @@ -43,6 +45,7 @@ protected Class[] getAnnotatedClasses() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSave() { inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java index 6d903880aa8a..6c6fd169dac0 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/manytoone/referencedcolumnname/ManyToOneReferencedColumnNameTest.java @@ -9,10 +9,12 @@ import org.hibernate.Session; import org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl; import org.hibernate.cfg.Configuration; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.Test; /** @@ -21,6 +23,7 @@ public class ManyToOneReferencedColumnNameTest extends BaseCoreFunctionalTestCase { @Test @RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testRecoverableExceptionInFkOrdering() throws Exception { //SF should not blow up Vendor v = new Vendor(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/mapsid/MapsIdClassTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/mapsid/MapsIdClassTest.java index a62eb6f18f0d..d632820bdc36 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/mapsid/MapsIdClassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/mapsid/MapsIdClassTest.java @@ -4,6 +4,19 @@ */ package org.hibernate.orm.test.annotations.mapsid; +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.dialect.GaussDBDialect; + +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +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.Test; + import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -15,37 +28,31 @@ import jakarta.persistence.OneToMany; import jakarta.persistence.PrimaryKeyJoinColumn; import jakarta.persistence.Table; -import org.hibernate.testing.orm.junit.DialectFeatureChecks; -import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.RequiresDialectFeature; -import org.hibernate.testing.orm.junit.SessionFactory; -import org.hibernate.testing.orm.junit.SessionFactoryScope; -import org.junit.jupiter.api.Test; - -import java.util.HashSet; -import java.util.Set; -import static jakarta.persistence.CascadeType.*; +import static jakarta.persistence.CascadeType.MERGE; +import static jakarta.persistence.CascadeType.PERSIST; +import static jakarta.persistence.CascadeType.REMOVE; import static org.junit.jupiter.api.Assertions.assertEquals; @SessionFactory @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) -@DomainModel(annotatedClasses ={MapsIdClassTest.User.class, MapsIdClassTest.UserAuthority.class}) +@DomainModel(annotatedClasses = { MapsIdClassTest.User.class, MapsIdClassTest.UserAuthority.class }) public class MapsIdClassTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") void test(SessionFactoryScope scope) { - scope.inTransaction( s-> { + scope.inTransaction( s -> { User ue = new User(); - ue.setName("Gavin"); + ue.setName( "Gavin" ); UserAuthority uae = new UserAuthority(); - ue.addUserAuthority(uae); - uae.setUser(ue); - uae.setAuthority("God"); - s.persist(ue); + ue.addUserAuthority( uae ); + uae.setUser( ue ); + uae.setAuthority( "God" ); + s.persist( ue ); s.flush(); assertEquals( ue.id, uae.userId ); - }); + } ); } @@ -74,13 +81,13 @@ public void setName(String name) { } @OneToMany( - cascade = {PERSIST, MERGE, REMOVE}, + cascade = { PERSIST, MERGE, REMOVE }, mappedBy = "user", orphanRemoval = true) private Set userAuthorities = new HashSet<>(); public void addUserAuthority(UserAuthority userAuthority) { - this.userAuthorities.add(userAuthority); + this.userAuthorities.add( userAuthority ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/query/QueryAndSQLTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/query/QueryAndSQLTest.java index 4678d372f113..f5a09b2dba4c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/query/QueryAndSQLTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/query/QueryAndSQLTest.java @@ -14,6 +14,7 @@ import org.hibernate.Transaction; import org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl; import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -560,6 +561,9 @@ public void testNativeQueryAndCompositePKAndComponents(SessionFactoryScope scope } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, + reason = "type:resolved.If you operate a table with the same name as the system view under the schema, " + + "you will be redirected to the system view and an error will be reported.") public void testDiscriminator(SessionFactoryScope scope) { scope.inSession( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/ejb3/PreParsedOrmXmlTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/ejb3/PreParsedOrmXmlTest.java index b6c0e7f080c7..7f78547cda4c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/ejb3/PreParsedOrmXmlTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/ejb3/PreParsedOrmXmlTest.java @@ -11,20 +11,22 @@ import org.hibernate.boot.jaxb.spi.Binding; import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; import org.hibernate.cfg.Configuration; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.JiraKeyGroup; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; -@JiraKeyGroup( value = { - @JiraKey( value = "HHH-14530" ), - @JiraKey( value = "HHH-14529" ) -} ) +@JiraKeyGroup(value = { + @JiraKey(value = "HHH-14530"), + @JiraKey(value = "HHH-14529") +}) @RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class) public class PreParsedOrmXmlTest extends BaseCoreFunctionalTestCase { @@ -47,6 +49,7 @@ protected void addMappings(Configuration configuration) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testPreParsedOrmXml() { // Just check that the entity can be persisted, which means the mapping file was taken into account NonAnnotatedEntity persistedEntity = new NonAnnotatedEntity( "someName" ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/hbm/HbmWithIdentityTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/hbm/HbmWithIdentityTest.java index 84d7cadb743f..2b26990cf2f9 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/hbm/HbmWithIdentityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/hbm/HbmWithIdentityTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.annotations.xml.hbm; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.HANADialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -31,6 +32,7 @@ public class HbmWithIdentityTest { @Test @SkipForDialect(dialectClass = HANADialect.class, matchSubTypes = true, reason = " HANA doesn't support tables consisting of only a single auto-generated column") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testManyToOneAndInterface(SessionFactoryScope scope) { scope.inTransaction( s -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/hbm/PreParsedHbmXmlTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/hbm/PreParsedHbmXmlTest.java index 816d9f2e32ac..38775284639c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/hbm/PreParsedHbmXmlTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/xml/hbm/PreParsedHbmXmlTest.java @@ -10,11 +10,13 @@ import org.hibernate.boot.MetadataSources; import org.hibernate.boot.jaxb.spi.Binding; +import org.hibernate.dialect.GaussDBDialect; +import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest; import org.hibernate.testing.orm.junit.DialectFeatureChecks; -import org.hibernate.testing.orm.junit.RequiresDialectFeature; import org.hibernate.testing.orm.junit.JiraKey; -import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -36,6 +38,7 @@ protected void applyMetadataSources(MetadataSources metadataSources) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testPreParsedHbmXml() { // Just check that the entity can be persisted, which means the mapping file was taken into account NonAnnotatedEntity persistedEntity = new NonAnnotatedEntity( "someName" ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/scanning/PackagedEntityManagerTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/scanning/PackagedEntityManagerTest.java index 29f4ef580ea1..9ae2197f8ca8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/scanning/PackagedEntityManagerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/scanning/PackagedEntityManagerTest.java @@ -11,6 +11,7 @@ import org.hibernate.SessionFactory; import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.event.service.spi.EventListenerRegistry; import org.hibernate.event.spi.EventType; @@ -37,6 +38,7 @@ import org.hibernate.orm.test.jpa.pack.various.Seat; import org.hibernate.stat.Statistics; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.hibernate.testing.transaction.TransactionUtil; import org.hibernate.testing.util.ServiceRegistryUtil; import org.junit.jupiter.api.AfterEach; @@ -63,11 +65,13 @@ * @author Gavin King * @author Hardy Ferentschik */ +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class PackagedEntityManagerTest extends PackagingTestCase { private EntityManagerFactory emf; + @AfterEach - public void tearDown(){ - if(emf != null && emf.isOpen()) { + public void tearDown() { + if ( emf != null && emf.isOpen() ) { emf.close(); } } @@ -79,29 +83,31 @@ public void testDefaultPar() throws Exception { // run the test emf = Persistence.createEntityManagerFactory( "defaultpar", ServiceRegistryUtil.createBaseSettings() ); - TransactionUtil.doInJPA( () -> emf, em -> { - ApplicationServer as = new ApplicationServer(); - as.setName( "JBoss AS" ); - Version v = new Version(); - v.setMajor( 4 ); - v.setMinor( 0 ); - v.setMicro( 3 ); - as.setVersion( v ); - Mouse mouse = new Mouse(); - mouse.setName( "mickey" ); - em.persist( as ); - em.persist( mouse ); - assertEquals( 1, em.createNamedQuery( "allMouse" ).getResultList().size() ); - Lighter lighter = new Lighter(); - lighter.name = "main"; - lighter.power = " 250 W"; - em.persist( lighter ); - em.flush(); - em.remove( lighter ); - em.remove( mouse ); - assertNotNull( as.getId() ); - em.remove( as ); - } ); + TransactionUtil.doInJPA( + () -> emf, em -> { + ApplicationServer as = new ApplicationServer(); + as.setName( "JBoss AS" ); + Version v = new Version(); + v.setMajor( 4 ); + v.setMinor( 0 ); + v.setMicro( 3 ); + as.setVersion( v ); + Mouse mouse = new Mouse(); + mouse.setName( "mickey" ); + em.persist( as ); + em.persist( mouse ); + assertEquals( 1, em.createNamedQuery( "allMouse" ).getResultList().size() ); + Lighter lighter = new Lighter(); + lighter.name = "main"; + lighter.power = " 250 W"; + em.persist( lighter ); + em.flush(); + em.remove( lighter ); + em.remove( mouse ); + assertNotNull( as.getId() ); + em.remove( as ); + } + ); } @Test @@ -110,29 +116,31 @@ public void testDefaultParForPersistence_1_0() throws Exception { addPackageToClasspath( testPackage ); emf = Persistence.createEntityManagerFactory( "defaultpar_1_0", ServiceRegistryUtil.createBaseSettings() ); - TransactionUtil.doInJPA( () -> emf, em -> { - ApplicationServer1 as = new ApplicationServer1(); - as.setName( "JBoss AS" ); - Version1 v = new Version1(); - v.setMajor( 4 ); - v.setMinor( 0 ); - v.setMicro( 3 ); - as.setVersion( v ); - Mouse1 mouse = new Mouse1(); - mouse.setName( "mickey" ); - em.persist( as ); - em.persist( mouse ); - assertEquals( 1, em.createNamedQuery( "allMouse_1_0" ).getResultList().size() ); - Lighter1 lighter = new Lighter1(); - lighter.name = "main"; - lighter.power = " 250 W"; - em.persist( lighter ); - em.flush(); - em.remove( lighter ); - em.remove( mouse ); - assertNotNull( as.getId() ); - em.remove( as ); - } ); + TransactionUtil.doInJPA( + () -> emf, em -> { + ApplicationServer1 as = new ApplicationServer1(); + as.setName( "JBoss AS" ); + Version1 v = new Version1(); + v.setMajor( 4 ); + v.setMinor( 0 ); + v.setMicro( 3 ); + as.setVersion( v ); + Mouse1 mouse = new Mouse1(); + mouse.setName( "mickey" ); + em.persist( as ); + em.persist( mouse ); + assertEquals( 1, em.createNamedQuery( "allMouse_1_0" ).getResultList().size() ); + Lighter1 lighter = new Lighter1(); + lighter.name = "main"; + lighter.power = " 250 W"; + em.persist( lighter ); + em.flush(); + em.remove( lighter ); + em.remove( mouse ); + assertNotNull( as.getId() ); + em.remove( as ); + } + ); } @Test @@ -143,33 +151,35 @@ public void testListenersDefaultPar() throws Exception { IncrementListener.reset(); OtherIncrementListener.reset(); emf = Persistence.createEntityManagerFactory( "defaultpar", ServiceRegistryUtil.createBaseSettings() ); - TransactionUtil.doInJPA( () -> emf, em -> { - ApplicationServer as = new ApplicationServer(); - as.setName( "JBoss AS" ); - Version v = new Version(); - v.setMajor( 4 ); - v.setMinor( 0 ); - v.setMicro( 3 ); - as.setVersion( v ); - em.persist( as ); - em.flush(); - assertEquals( 1, IncrementListener.getIncrement(), "Failure in default listeners" ); - assertEquals( 1, OtherIncrementListener.getIncrement(), "Failure in XML overridden listeners" ); - - Mouse mouse = new Mouse(); - mouse.setName( "mickey" ); - em.persist( mouse ); - em.flush(); - assertEquals( 1, IncrementListener.getIncrement(), "Failure in @ExcludeDefaultListeners" ); - assertEquals( 1, OtherIncrementListener.getIncrement() ); - - Money money = new Money(); - em.persist( money ); - em.flush(); - assertEquals( 2, IncrementListener.getIncrement(), "Failure in @ExcludeDefaultListeners" ); - assertEquals( 1, OtherIncrementListener.getIncrement() ); - em.getTransaction().setRollbackOnly(); - } ); + TransactionUtil.doInJPA( + () -> emf, em -> { + ApplicationServer as = new ApplicationServer(); + as.setName( "JBoss AS" ); + Version v = new Version(); + v.setMajor( 4 ); + v.setMinor( 0 ); + v.setMicro( 3 ); + as.setVersion( v ); + em.persist( as ); + em.flush(); + assertEquals( 1, IncrementListener.getIncrement(), "Failure in default listeners" ); + assertEquals( 1, OtherIncrementListener.getIncrement(), "Failure in XML overridden listeners" ); + + Mouse mouse = new Mouse(); + mouse.setName( "mickey" ); + em.persist( mouse ); + em.flush(); + assertEquals( 1, IncrementListener.getIncrement(), "Failure in @ExcludeDefaultListeners" ); + assertEquals( 1, OtherIncrementListener.getIncrement() ); + + Money money = new Money(); + em.persist( money ); + em.flush(); + assertEquals( 2, IncrementListener.getIncrement(), "Failure in @ExcludeDefaultListeners" ); + assertEquals( 1, OtherIncrementListener.getIncrement() ); + em.getTransaction().setRollbackOnly(); + } + ); } @Test @@ -178,17 +188,19 @@ public void testExplodedPar() throws Exception { addPackageToClasspath( testPackage ); emf = Persistence.createEntityManagerFactory( "explodedpar", ServiceRegistryUtil.createBaseSettings() ); - TransactionUtil.doInJPA( () -> emf, em -> { - Carpet carpet = new Carpet(); - Elephant el = new Elephant(); - el.setName( "Dumbo" ); - carpet.setCountry( "Turkey" ); - em.persist( carpet ); - em.persist( el ); - assertEquals( 1, em.createNamedQuery( "allCarpet" ).getResultList().size() ); - assertNotNull( carpet.getId() ); - em.remove( carpet ); - } ); + TransactionUtil.doInJPA( + () -> emf, em -> { + Carpet carpet = new Carpet(); + Elephant el = new Elephant(); + el.setName( "Dumbo" ); + carpet.setCountry( "Turkey" ); + em.persist( carpet ); + em.persist( el ); + assertEquals( 1, em.createNamedQuery( "allCarpet" ).getResultList().size() ); + assertNotNull( carpet.getId() ); + em.remove( carpet ); + } + ); } @Test @@ -199,7 +211,7 @@ public void testExcludeHbmPar() throws Exception { try { emf = Persistence.createEntityManagerFactory( "excludehbmpar", ServiceRegistryUtil.createBaseSettings() ); } - catch ( PersistenceException e ) { + catch (PersistenceException e) { if ( emf != null ) { emf.close(); } @@ -217,15 +229,17 @@ public void testExcludeHbmPar() throws Exception { fail( "Try to process hbm file: " + e.getMessage() ); } - TransactionUtil.doInJPA( () -> emf, em -> { - Caipirinha s = new Caipirinha( "Strong" ); - em.persist( s ); - em.getTransaction().commit(); - - em.getTransaction().begin(); - s = em.find( Caipirinha.class, s.getId() ); - em.remove( s ); - } ); + TransactionUtil.doInJPA( + () -> emf, em -> { + Caipirinha s = new Caipirinha( "Strong" ); + em.persist( s ); + em.getTransaction().commit(); + + em.getTransaction().begin(); + s = em.find( Caipirinha.class, s.getId() ); + em.remove( s ); + } + ); } @Test @@ -237,21 +251,23 @@ public void testCfgXmlPar() throws Exception { assertTrue( emf.getProperties().containsKey( "hibernate.test-assertable-setting" ) ); - TransactionUtil.doInJPA( () -> emf, em -> { - Item i = new Item(); - i.setDescr( "Blah" ); - i.setName( "factory" ); - Morito m = new Morito(); - m.setPower( "SuperStrong" ); - em.persist( i ); - em.persist( m ); - em.getTransaction().commit(); - - em.getTransaction().begin(); - i = em.find( Item.class, i.getName() ); - em.remove( i ); - em.remove( em.find( Morito.class, m.getId() ) ); - } ); + TransactionUtil.doInJPA( + () -> emf, em -> { + Item i = new Item(); + i.setDescr( "Blah" ); + i.setName( "factory" ); + Morito m = new Morito(); + m.setPower( "SuperStrong" ); + em.persist( i ); + em.persist( m ); + em.getTransaction().commit(); + + em.getTransaction().begin(); + i = em.find( Item.class, i.getName() ); + em.remove( i ); + em.remove( em.find( Morito.class, m.getId() ) ); + } + ); } @Test @@ -260,15 +276,17 @@ public void testSpacePar() throws Exception { addPackageToClasspath( testPackage ); emf = Persistence.createEntityManagerFactory( "space par", ServiceRegistryUtil.createBaseSettings() ); - TransactionUtil.doInJPA( () -> emf, em -> { - org.hibernate.orm.test.jpa.pack.spacepar.Bug bug = new org.hibernate.orm.test.jpa.pack.spacepar.Bug(); - bug.setSubject( "Spaces in directory name don't play well on Windows" ); - em.persist( bug ); - em.flush(); - em.remove( bug ); - assertNotNull( bug.getId() ); - em.getTransaction().setRollbackOnly(); - } ); + TransactionUtil.doInJPA( + () -> emf, em -> { + org.hibernate.orm.test.jpa.pack.spacepar.Bug bug = new org.hibernate.orm.test.jpa.pack.spacepar.Bug(); + bug.setSubject( "Spaces in directory name don't play well on Windows" ); + em.persist( bug ); + em.flush(); + em.remove( bug ); + assertNotNull( bug.getId() ); + em.getTransaction().setRollbackOnly(); + } + ); } @Test @@ -283,15 +301,17 @@ public void testOverriddenPar() throws Exception { //noinspection rawtypes properties.putAll( (Map) p ); emf = Persistence.createEntityManagerFactory( "overridenpar", properties ); - TransactionUtil.doInJPA( () -> emf, em -> { - org.hibernate.orm.test.jpa.pack.overridenpar.Bug bug = new org.hibernate.orm.test.jpa.pack.overridenpar.Bug(); - bug.setSubject( "Allow DS overriding" ); - em.persist( bug ); - em.flush(); - em.remove( bug ); - assertNotNull( bug.getId() ); - em.getTransaction().setRollbackOnly(); - } ); + TransactionUtil.doInJPA( + () -> emf, em -> { + org.hibernate.orm.test.jpa.pack.overridenpar.Bug bug = new org.hibernate.orm.test.jpa.pack.overridenpar.Bug(); + bug.setSubject( "Allow DS overriding" ); + em.persist( bug ); + em.flush(); + em.remove( bug ); + assertNotNull( bug.getId() ); + em.getTransaction().setRollbackOnly(); + } + ); } @Test @@ -321,44 +341,47 @@ public void testExtendedEntityManager() throws Exception { addPackageToClasspath( testPackage ); emf = Persistence.createEntityManagerFactory( "manager1", ServiceRegistryUtil.createBaseSettings() ); - TransactionUtil.doInJPA( () -> emf, em -> { - Item item = new Item( "Mouse", "Micro$oft mouse" ); - em.persist( item ); - assertTrue( em.contains( item ) ); - em.getTransaction().commit(); - - assertTrue( em.contains( item ) ); - - em.getTransaction().begin(); - Item item1 = (Item) em.createQuery( "select i from Item i where descr like 'M%'" ).getSingleResult(); - assertNotNull( item1 ); - assertSame( item, item1 ); - item.setDescr( "Micro$oft wireless mouse" ); - assertTrue( em.contains( item ) ); - em.getTransaction().commit(); - - assertTrue( em.contains( item ) ); - - em.getTransaction().begin(); - item1 = em.find( Item.class, "Mouse" ); - assertSame( item, item1 ); - em.getTransaction().commit(); - assertTrue( em.contains( item ) ); - - item1 = em.find( Item.class, "Mouse" ); - assertSame( item, item1 ); - assertTrue( em.contains( item ) ); - - item1 = (Item) em.createQuery( "select i from Item i where descr like 'M%'" ).getSingleResult(); - assertNotNull( item1 ); - assertSame( item, item1 ); - assertTrue( em.contains( item ) ); - - em.getTransaction().begin(); - assertTrue( em.contains( item ) ); - em.remove( item ); - em.remove( item ); //second remove should be a no-op - } ); + TransactionUtil.doInJPA( + () -> emf, em -> { + Item item = new Item( "Mouse", "Micro$oft mouse" ); + em.persist( item ); + assertTrue( em.contains( item ) ); + em.getTransaction().commit(); + + assertTrue( em.contains( item ) ); + + em.getTransaction().begin(); + Item item1 = (Item) em.createQuery( "select i from Item i where descr like 'M%'" ) + .getSingleResult(); + assertNotNull( item1 ); + assertSame( item, item1 ); + item.setDescr( "Micro$oft wireless mouse" ); + assertTrue( em.contains( item ) ); + em.getTransaction().commit(); + + assertTrue( em.contains( item ) ); + + em.getTransaction().begin(); + item1 = em.find( Item.class, "Mouse" ); + assertSame( item, item1 ); + em.getTransaction().commit(); + assertTrue( em.contains( item ) ); + + item1 = em.find( Item.class, "Mouse" ); + assertSame( item, item1 ); + assertTrue( em.contains( item ) ); + + item1 = (Item) em.createQuery( "select i from Item i where descr like 'M%'" ).getSingleResult(); + assertNotNull( item1 ); + assertSame( item, item1 ); + assertTrue( em.contains( item ) ); + + em.getTransaction().begin(); + assertTrue( em.contains( item ) ); + em.remove( item ); + em.remove( item ); //second remove should be a no-op + } + ); } @Test @@ -376,30 +399,36 @@ public void testConfiguration() throws Exception { stats.clear(); stats.setStatisticsEnabled( true ); - TransactionUtil.doInJPA( () -> emf, em -> { - em.persist( res ); - em.persist( item ); - assertTrue( em.contains( item ) ); - } ); + TransactionUtil.doInJPA( + () -> emf, em -> { + em.persist( res ); + em.persist( item ); + assertTrue( em.contains( item ) ); + } + ); assertEquals( 1, stats.getSecondLevelCachePutCount() ); assertEquals( 0, stats.getSecondLevelCacheHitCount() ); - TransactionUtil.doInJPA( () -> emf, em -> { - Item second = em.find( Item.class, item.getName() ); - assertEquals( 1, second.getDistributors().size() ); - assertEquals( 1, stats.getSecondLevelCacheHitCount() ); - } ); - - TransactionUtil.doInJPA( () -> emf, em -> { - Item second = em.find( Item.class, item.getName() ); - assertEquals( 1, second.getDistributors().size() ); - assertEquals( 3, stats.getSecondLevelCacheHitCount() ); - for ( Distributor distro : second.getDistributors() ) { - em.remove( distro ); - } - em.remove( second ); - } ); + TransactionUtil.doInJPA( + () -> emf, em -> { + Item second = em.find( Item.class, item.getName() ); + assertEquals( 1, second.getDistributors().size() ); + assertEquals( 1, stats.getSecondLevelCacheHitCount() ); + } + ); + + TransactionUtil.doInJPA( + () -> emf, em -> { + Item second = em.find( Item.class, item.getName() ); + assertEquals( 1, second.getDistributors().size() ); + assertEquals( 3, stats.getSecondLevelCacheHitCount() ); + for ( Distributor distro : second.getDistributors() ) { + em.remove( distro ); + } + em.remove( second ); + } + ); stats.clear(); stats.setStatisticsEnabled( false ); @@ -412,18 +441,22 @@ public void testExternalJar() throws Exception { addPackageToClasspath( testPackage, externalJar ); emf = Persistence.createEntityManagerFactory( "manager1", ServiceRegistryUtil.createBaseSettings() ); - Scooter scooter = TransactionUtil.doInJPA( () -> emf, em -> { - Scooter s = new Scooter(); - s.setModel( "Abadah" ); - s.setSpeed( 85l ); - em.persist( s ); - return s; - } ); - TransactionUtil.doInJPA( () -> emf, em -> { - Scooter s = em.find( Scooter.class, scooter.getModel() ); - assertEquals( Long.valueOf( 85 ), s.getSpeed() ); - em.remove( s ); - } ); + Scooter scooter = TransactionUtil.doInJPA( + () -> emf, em -> { + Scooter s = new Scooter(); + s.setModel( "Abadah" ); + s.setSpeed( 85l ); + em.persist( s ); + return s; + } + ); + TransactionUtil.doInJPA( + () -> emf, em -> { + Scooter s = em.find( Scooter.class, scooter.getModel() ); + assertEquals( Long.valueOf( 85 ), s.getSpeed() ); + em.remove( s ); + } + ); } @Test @@ -440,18 +473,22 @@ public void testRelativeJarReferences() throws Exception { emf.getMetamodel().entity( Scooter.class ); // additionally, try to use them - Scooter scooter = TransactionUtil.doInJPA( () -> emf, em -> { - Scooter s = new Scooter(); - s.setModel( "Abadah" ); - s.setSpeed( 85l ); - em.persist( s ); - return s; - } ); - TransactionUtil.doInJPA( () -> emf, em -> { - Scooter s = em.find( Scooter.class, scooter.getModel() ); - assertEquals( Long.valueOf( 85 ), s.getSpeed() ); - em.remove( s ); - } ); + Scooter scooter = TransactionUtil.doInJPA( + () -> emf, em -> { + Scooter s = new Scooter(); + s.setModel( "Abadah" ); + s.setSpeed( 85l ); + em.persist( s ); + return s; + } + ); + TransactionUtil.doInJPA( + () -> emf, em -> { + Scooter s = em.find( Scooter.class, scooter.getModel() ); + assertEquals( Long.valueOf( 85 ), s.getSpeed() ); + em.remove( s ); + } + ); } @Test @@ -460,15 +497,17 @@ public void testORMFileOnMainAndExplicitJars() throws Exception { addPackageToClasspath( testPackage ); emf = Persistence.createEntityManagerFactory( "manager1", ServiceRegistryUtil.createBaseSettings() ); - TransactionUtil.doInJPA( () -> emf, em -> { - Seat seat = new Seat(); - seat.setNumber( "3B" ); - Airplane plane = new Airplane(); - plane.setSerialNumber( "75924418409052355" ); - em.persist( seat ); - em.persist( plane ); - em.flush(); - em.getTransaction().setRollbackOnly(); - }); + TransactionUtil.doInJPA( + () -> emf, em -> { + Seat seat = new Seat(); + seat.setNumber( "3B" ); + Airplane plane = new Airplane(); + plane.setSerialNumber( "75924418409052355" ); + em.persist( seat ); + em.persist( plane ); + em.flush(); + em.getTransaction().setRollbackOnly(); + } + ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/scanning/ScannerTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/scanning/ScannerTest.java index 1c978909d5fa..04b2a2cdce28 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/scanning/ScannerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/scanning/ScannerTest.java @@ -4,15 +4,10 @@ */ package org.hibernate.orm.test.bootstrap.scanning; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; - import java.io.File; import java.io.InputStream; import java.io.Serializable; import java.util.Map; -import jakarta.persistence.EntityManagerFactory; -import jakarta.persistence.Persistence; import org.hibernate.archive.scan.internal.StandardScanner; import org.hibernate.boot.archive.scan.internal.DisabledScanner; @@ -25,16 +20,28 @@ import org.hibernate.boot.archive.scan.spi.ScanResult; import org.hibernate.boot.archive.scan.spi.Scanner; import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.internal.util.SerializationHelper; import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor; import org.hibernate.jpa.boot.internal.StandardJpaScanEnvironmentImpl; import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor; import org.hibernate.orm.test.jpa.pack.defaultpar.ApplicationServer; import org.hibernate.orm.test.jpa.pack.defaultpar.Version; + import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.hibernate.testing.util.ServiceRegistryUtil; import org.junit.jupiter.api.Test; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.Persistence; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + /** * @author Emmanuel Bernard @@ -80,6 +87,7 @@ private void assertClassesContained(ScanResult scanResult, Class classToCheckFor } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testCustomScanner() throws Exception { File defaultPar = buildDefaultPar(); File explicitPar = buildExplicitPar(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingNotInDefaultFetchGroupPersistTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingNotInDefaultFetchGroupPersistTest.java index a1c4e9d1215d..2c637e453037 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingNotInDefaultFetchGroupPersistTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingNotInDefaultFetchGroupPersistTest.java @@ -9,6 +9,8 @@ import java.util.Date; import java.util.List; +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; @@ -16,6 +18,8 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.Test; import jakarta.persistence.Basic; import jakarta.persistence.CascadeType; @@ -34,8 +38,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; -import org.junit.jupiter.api.Test; - /** * @author Christian Beikov */ @@ -52,6 +54,7 @@ public class DirtyTrackingNotInDefaultFetchGroupPersistTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void test(SessionFactoryScope scope) { assertFalse( scope.getSessionFactory().getSessionFactoryOptions().isCollectionsInDefaultFetchGroupEnabled() ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingPersistTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingPersistTest.java index 013787d261e6..eed011b2deb0 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingPersistTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/dirty/DirtyTrackingPersistTest.java @@ -8,6 +8,19 @@ import java.util.Collections; import java.util.Date; import java.util.List; + +import org.hibernate.dialect.GaussDBDialect; + +import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +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.Test; + import jakarta.persistence.Basic; import jakarta.persistence.CascadeType; import jakarta.persistence.ElementCollection; @@ -23,18 +36,8 @@ import jakarta.persistence.Temporal; import jakarta.persistence.TemporalType; -import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; -import org.hibernate.testing.orm.junit.DialectFeatureChecks; -import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.JiraKey; -import org.hibernate.testing.orm.junit.RequiresDialectFeature; -import org.hibernate.testing.orm.junit.SessionFactory; -import org.hibernate.testing.orm.junit.SessionFactoryScope; - import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; - /** * @author Christian Beikov */ @@ -47,6 +50,7 @@ @SessionFactory @BytecodeEnhanced @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class DirtyTrackingPersistTest { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/LazyBasicFieldMergeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/LazyBasicFieldMergeTest.java index 12b7b9905b3a..57293166ee1c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/LazyBasicFieldMergeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/LazyBasicFieldMergeTest.java @@ -4,6 +4,16 @@ */ package org.hibernate.orm.test.bytecode.enhancement.lazy; +import org.hibernate.dialect.GaussDBDialect; + +import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; +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.Test; + import jakarta.persistence.Basic; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -15,17 +25,9 @@ import jakarta.persistence.OneToOne; import jakarta.persistence.Table; -import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; -import org.hibernate.testing.orm.junit.DomainModel; -import org.hibernate.testing.orm.junit.JiraKey; -import org.hibernate.testing.orm.junit.SessionFactory; -import org.hibernate.testing.orm.junit.SessionFactoryScope; - import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Test; - /** * @author Vlad Mihalcea */ @@ -41,17 +43,18 @@ public class LazyBasicFieldMergeTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void test(SessionFactoryScope scope) { scope.inTransaction( session -> { Manager manager = new Manager(); - manager.setName("John Doe"); - manager.setResume(new byte[] {1, 2, 3}); + manager.setName( "John Doe" ); + manager.setResume( new byte[] { 1, 2, 3 } ); Company company = new Company(); - company.setName("Company"); - company.setManager(manager); + company.setName( "Company" ); + company.setManager( manager ); - Company _company = (Company) session.merge( company); + Company _company = (Company) session.merge( company ); assertEquals( company.getName(), _company.getName() ); assertArrayEquals( company.getManager().getResume(), _company.getManager().getResume() ); } ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/LazyInitializationWithoutInlineDirtyTrackingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/LazyInitializationWithoutInlineDirtyTrackingTest.java index 3f361fe9c266..e41a807ea3c3 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/LazyInitializationWithoutInlineDirtyTrackingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/LazyInitializationWithoutInlineDirtyTrackingTest.java @@ -4,15 +4,8 @@ */ package org.hibernate.orm.test.bytecode.enhancement.lazy; -import jakarta.persistence.Basic; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.Id; -import jakarta.persistence.Lob; -import jakarta.persistence.Table; - import org.hibernate.bytecode.enhance.spi.UnloadedClass; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; @@ -21,8 +14,17 @@ import org.hibernate.testing.orm.junit.JiraKey; 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.Test; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.Table; + /** * @author Guillaume Smet */ @@ -34,23 +36,27 @@ ) @SessionFactory @BytecodeEnhanced -@CustomEnhancementContext( {EnhancerTestContext.class, LazyInitializationWithoutInlineDirtyTrackingTest.NoInlineDirtyTrackingContext.class} ) +@CustomEnhancementContext({ + EnhancerTestContext.class, + LazyInitializationWithoutInlineDirtyTrackingTest.NoInlineDirtyTrackingContext.class +}) public class LazyInitializationWithoutInlineDirtyTrackingTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void test(SessionFactoryScope scope) { scope.inTransaction( s -> { File file = new File(); file.setId( 1L ); file.setName( "file" ); - file.setBytes( new byte[]{ 0 } ); + file.setBytes( new byte[] { 0 } ); s.persist( file ); } ); scope.inTransaction( s -> { File file = s.find( File.class, 1L ); - file.setBytes( new byte[]{ 1 } ); + file.setBytes( new byte[] { 1 } ); s.persist( file ); } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/DirtyCheckPrivateUnMappedCollectionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/DirtyCheckPrivateUnMappedCollectionTest.java index 720d138629cf..6002672d2be5 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/DirtyCheckPrivateUnMappedCollectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/DirtyCheckPrivateUnMappedCollectionTest.java @@ -4,23 +4,14 @@ */ package org.hibernate.orm.test.bytecode.enhancement.lazy.proxy.inlinedirtychecking; -import static org.junit.jupiter.api.Assumptions.assumeFalse; - import java.util.ArrayList; import java.util.Collections; import java.util.List; -import jakarta.persistence.AttributeConverter; -import jakarta.persistence.Convert; -import jakarta.persistence.Converter; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.MappedSuperclass; import org.hibernate.bytecode.internal.BytecodeProviderInitiator; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; @@ -31,9 +22,21 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Convert; +import jakarta.persistence.Converter; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; + +import static org.junit.jupiter.api.Assumptions.assumeFalse; + /** * @author Andrea Boriero */ @@ -44,8 +47,8 @@ ) @ServiceRegistry( settings = { - @Setting( name = AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, value = "100" ), - @Setting( name = AvailableSettings.GENERATE_STATISTICS, value = "true" ), + @Setting(name = AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, value = "100"), + @Setting(name = AvailableSettings.GENERATE_STATISTICS, value = "true"), } ) @SessionFactory @@ -62,6 +65,7 @@ static void beforeAll() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testIt(SessionFactoryScope scope) { scope.inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/LoadAndUpdateEntitiesWithCollectionsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/LoadAndUpdateEntitiesWithCollectionsTest.java index 674fbcb31c04..89a111147b2a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/LoadAndUpdateEntitiesWithCollectionsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/LoadAndUpdateEntitiesWithCollectionsTest.java @@ -6,14 +6,11 @@ import java.util.HashSet; import java.util.List; -import jakarta.persistence.TypedQuery; -import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.CriteriaQuery; -import jakarta.persistence.criteria.Root; import org.hibernate.bytecode.internal.BytecodeProviderInitiator; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; @@ -26,11 +23,17 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import jakarta.persistence.TypedQuery; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; + import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.junit.jupiter.api.Assumptions.assumeFalse; @@ -46,14 +49,15 @@ ) @ServiceRegistry( settings = { - @Setting( name = AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, value = "100" ), - @Setting( name = AvailableSettings.GENERATE_STATISTICS, value = "true" ), + @Setting(name = AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, value = "100"), + @Setting(name = AvailableSettings.GENERATE_STATISTICS, value = "true"), } ) @SessionFactory @BytecodeEnhanced @CustomEnhancementContext({ DirtyCheckEnhancementContext.class, NoDirtyCheckEnhancementContext.class }) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class LoadAndUpdateEntitiesWithCollectionsTest { @BeforeAll diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/dynamicupdate/DynamicUpdateAndCollectionsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/dynamicupdate/DynamicUpdateAndCollectionsTest.java index 6cca4808a4c9..95dd223f157b 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/dynamicupdate/DynamicUpdateAndCollectionsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/inlinedirtychecking/dynamicupdate/DynamicUpdateAndCollectionsTest.java @@ -4,20 +4,16 @@ */ package org.hibernate.orm.test.bytecode.enhancement.lazy.proxy.inlinedirtychecking.dynamicupdate; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeFalse; - import java.util.HashSet; import java.util.List; -import jakarta.persistence.TypedQuery; -import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.CriteriaQuery; -import jakarta.persistence.criteria.Root; import org.hibernate.bytecode.internal.BytecodeProviderInitiator; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.orm.test.bytecode.enhancement.lazy.proxy.inlinedirtychecking.DirtyCheckEnhancementContext; +import org.hibernate.orm.test.bytecode.enhancement.lazy.proxy.inlinedirtychecking.NoDirtyCheckEnhancementContext; import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; @@ -29,15 +25,20 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; - -import org.hibernate.orm.test.bytecode.enhancement.lazy.proxy.inlinedirtychecking.DirtyCheckEnhancementContext; -import org.hibernate.orm.test.bytecode.enhancement.lazy.proxy.inlinedirtychecking.NoDirtyCheckEnhancementContext; - +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import jakarta.persistence.TypedQuery; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeFalse; + @JiraKey("HHH14424") @DomainModel( annotatedClasses = { @@ -49,14 +50,15 @@ ) @ServiceRegistry( settings = { - @Setting( name = AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, value = "100" ), - @Setting( name = AvailableSettings.GENERATE_STATISTICS, value = "true" ), + @Setting(name = AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, value = "100"), + @Setting(name = AvailableSettings.GENERATE_STATISTICS, value = "true"), } ) @SessionFactory @BytecodeEnhanced @CustomEnhancementContext({ NoDirtyCheckEnhancementContext.class, DirtyCheckEnhancementContext.class }) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class DynamicUpdateAndCollectionsTest { @BeforeAll diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/merge/MergeUnsavedEntitiesTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/merge/MergeUnsavedEntitiesTest.java index 11c92368019b..88396400152f 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/merge/MergeUnsavedEntitiesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/merge/MergeUnsavedEntitiesTest.java @@ -9,12 +9,15 @@ import java.util.List; import java.util.Set; +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.Jira; import org.hibernate.testing.orm.junit.JiraKey; 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.Test; import jakarta.persistence.Entity; @@ -99,13 +102,14 @@ public void testMergeParentWithoutChildren(SessionFactoryScope scope) { scope.inTransaction( session -> { Parent parent = session.find( Parent.class, 1l ); - assertThat( parent.getChildren()).isEmpty(); + assertThat( parent.getChildren() ).isEmpty(); } ); } @Test @Jira("HHH-18177") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testMergeTransientInstanceWithGeneratedId(SessionFactoryScope scope) { Book merged = scope.fromTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/cid/CompositeIdAndMergeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/cid/CompositeIdAndMergeTest.java index ef62a5bef7ea..9fae651509d0 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/cid/CompositeIdAndMergeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/cid/CompositeIdAndMergeTest.java @@ -7,10 +7,13 @@ import java.util.ArrayList; import java.util.List; +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.JiraKey; 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.Test; import jakarta.persistence.CascadeType; @@ -38,6 +41,7 @@ public class CompositeIdAndMergeTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testMerge(SessionFactoryScope scope) { Integer lineItemIndex = 2; Order persistedOrder = scope.fromTransaction( diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/engine/spi/ExtraStateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/engine/spi/ExtraStateTest.java index 68ee9684ea5f..557f65adaae7 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/engine/spi/ExtraStateTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/engine/spi/ExtraStateTest.java @@ -4,24 +4,26 @@ */ package org.hibernate.orm.test.engine.spi; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; - +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityEntryExtraState; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.Test; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -31,14 +33,15 @@ * * @author Gunnar Morling */ -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsIdentityColumns.class, jiraKey = "HHH-9918") -@DomainModel( annotatedClasses = ExtraStateTest.ChineseTakeawayRestaurant.class ) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class, jiraKey = "HHH-9918") +@DomainModel(annotatedClasses = ExtraStateTest.ChineseTakeawayRestaurant.class) @SessionFactory public class ExtraStateTest { private SessionImplementor sessionRef; @Test @JiraKey(value = "HHH-9451") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void shouldMaintainExtraStateWhenUsingIdentityIdGenerationStrategy(SessionFactoryScope scope) { scope.inSession( (nonTransactedSession) -> { @@ -56,8 +59,12 @@ public void shouldMaintainExtraStateWhenUsingIdentityIdGenerationStrategy(Sessio } ); - TestExtraState extraState = getEntityEntry( persisted, nonTransactedSession ).getExtraState( TestExtraState.class ); - assertNotNull( extraState, "Test extra state was not propagated from temporary to final entity entry" ); + TestExtraState extraState = getEntityEntry( persisted, nonTransactedSession ).getExtraState( + TestExtraState.class ); + assertNotNull( + extraState, + "Test extra state was not propagated from temporary to final entity entry" + ); assertEquals( 311, extraState.getValue() ); sessionRef = null; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphAndJoinTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphAndJoinTest.java index d96296c4b93d..e85343706742 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphAndJoinTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphAndJoinTest.java @@ -6,6 +6,7 @@ import java.util.List; +import jakarta.persistence.EntityGraph; import org.hibernate.testing.jdbc.SQLStatementInspector; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.Jira; @@ -15,7 +16,6 @@ import org.junit.jupiter.api.Test; import jakarta.persistence.Entity; -import jakarta.persistence.EntityGraph; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; @@ -112,7 +112,7 @@ private void executeQuery(SessionFactoryScope scope, boolean criteria, boolean l final EntityGraph entityGraph = session.getEntityGraph( "test-graph" ); final List resultList = query.setHint( HINT_SPEC_FETCH_GRAPH, entityGraph ).getResultList(); assertThat( resultList ).hasSize( 2 ); - assertThat( resultList.stream().map( p -> p.getAddress().getId() ) ).containsExactly( 1L, 2L ); + assertThat( resultList.stream().map( p -> p.getAddress().getId() ) ).contains( 1L, 2L ); inspector.assertExecutedCount( 1 ); inspector.assertNumberOfOccurrenceInQuery( 0, "join", where ? 2 : 1 ); } ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/filter/FilterParameterTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/filter/FilterParameterTests.java index 150f6cbafe3d..dd3d80d02aec 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/filter/FilterParameterTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/filter/FilterParameterTests.java @@ -21,6 +21,7 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.community.dialect.AltibaseDialect; import org.hibernate.community.dialect.FirebirdDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.CockroachDialect; import org.hibernate.dialect.DB2Dialect; @@ -146,6 +147,7 @@ public void testNumeric(BiConsumer[] getAnnotatedClasses() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testFlushModeCommit() throws Exception { Session session = openSession(); try { @@ -51,6 +54,7 @@ public void testFlushModeCommit() throws Exception { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testFlushModeManual() throws Exception { Session session = openSession(); try { @@ -64,6 +68,7 @@ public void testFlushModeManual() throws Exception { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testFlushModeAuto() throws Exception { Session session = openSession(); try { @@ -95,7 +100,7 @@ private SelfRefEntity createAndInsertEntity(Session session) { return entity; } - catch ( Exception e ) { + catch (Exception e) { if ( session.getTransaction().isActive() ) { session.getTransaction().rollback(); } @@ -126,7 +131,7 @@ private SelfRefEntityWithEmbeddable createAndInsertEntityEmbeddable(Session sess return entity; } - catch ( Exception e ) { + catch (Exception e) { if ( session.getTransaction().isActive() ) { session.getTransaction().rollback(); } @@ -142,10 +147,16 @@ private void loadAndAssert(Session session, SelfRefEntity mergedEntity) { } private void loadAndInsert(Session session, SelfRefEntityWithEmbeddable mergedEntity) { - final SelfRefEntityWithEmbeddable loadedEntity = session.get( SelfRefEntityWithEmbeddable.class, mergedEntity.getId() ); + final SelfRefEntityWithEmbeddable loadedEntity = session.get( + SelfRefEntityWithEmbeddable.class, + mergedEntity.getId() + ); assertNotNull( "Expected to find the merged entity but did not.", loadedEntity ); assertEquals( "test", loadedEntity.getData() ); - assertNotNull( "Expected a non-null self reference in embeddable", loadedEntity.getInfo().getSeflRefEntityEmbedded() ); + assertNotNull( + "Expected a non-null self reference in embeddable", + loadedEntity.getInfo().getSeflRefEntityEmbedded() + ); } @Entity(name = "SelfRefEntity") diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayContainsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayContainsTest.java index e8f0b9f7ad33..3c01d4927b20 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayContainsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayContainsTest.java @@ -7,6 +7,7 @@ import java.util.Collection; import java.util.List; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.sqm.NodeBuilder; @@ -19,6 +20,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -32,7 +34,7 @@ */ @DomainModel(annotatedClasses = EntityWithArrays.class) @SessionFactory -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsStructuralArrays.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsStructuralArrays.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsArrayContains.class) // Clear the type cache, otherwise we might run into ORA-21700: object does not exist or is marked for delete @BootstrapServiceRegistry(integrators = SharedDriverManagerTypeCacheClearingIntegrator.class) @@ -41,8 +43,8 @@ public class ArrayContainsTest { @BeforeEach public void prepareData(SessionFactoryScope scope) { scope.inTransaction( em -> { - em.persist( new EntityWithArrays( 1L, new String[]{} ) ); - em.persist( new EntityWithArrays( 2L, new String[]{ "abc", null, "def" } ) ); + em.persist( new EntityWithArrays( 1L, new String[] {} ) ); + em.persist( new EntityWithArrays( 2L, new String[] { "abc", null, "def" } ) ); em.persist( new EntityWithArrays( 3L, null ) ); } ); } @@ -58,7 +60,10 @@ public void cleanup(SessionFactoryScope scope) { public void testContains(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-array-contains-example[] - List results = em.createQuery( "from EntityWithArrays e where array_contains(e.theArray, 'abc')", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where array_contains(e.theArray, 'abc')", + EntityWithArrays.class + ) .getResultList(); //end::hql-array-contains-example[] assertEquals( 1, results.size() ); @@ -69,13 +74,17 @@ public void testContains(SessionFactoryScope scope) { @Test public void testDoesNotContain(SessionFactoryScope scope) { scope.inSession( em -> { - List results = em.createQuery( "from EntityWithArrays e where array_contains(e.theArray, 'xyz')", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where array_contains(e.theArray, 'xyz')", + EntityWithArrays.class + ) .getResultList(); assertEquals( 0, results.size() ); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNodeBuilderArray(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -85,10 +94,10 @@ public void testNodeBuilderArray(SessionFactoryScope scope) { root.get( "id" ), cb.arrayContains( root.get( "theArray" ), cb.literal( "xyz" ) ), cb.arrayContains( root.get( "theArray" ), "xyz" ), - cb.arrayContains( new String[]{ "abc", "xyz" }, cb.literal( "xyz" ) ), + cb.arrayContains( new String[] { "abc", "xyz" }, cb.literal( "xyz" ) ), cb.arrayContainsNullable( root.get( "theArray" ), cb.literal( "xyz" ) ), cb.arrayContainsNullable( root.get( "theArray" ), "xyz" ), - cb.arrayContainsNullable( new String[]{ "abc", "xyz" }, cb.literal( "xyz" ) ) + cb.arrayContainsNullable( new String[] { "abc", "xyz" }, cb.literal( "xyz" ) ) ); em.createQuery( cq ).getResultList(); @@ -105,6 +114,7 @@ public void testNodeBuilderArray(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNodeBuilderCollection(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -115,7 +125,10 @@ public void testNodeBuilderCollection(SessionFactoryScope scope) { cb.collectionContains( root.>get( "theCollection" ), cb.literal( "xyz" ) ), cb.collectionContains( root.get( "theCollection" ), "xyz" ), cb.collectionContains( List.of( "abc", "xyz" ), cb.literal( "xyz" ) ), - cb.collectionContainsNullable( root.>get( "theCollection" ), cb.literal( "xyz" ) ), + cb.collectionContainsNullable( + root.>get( "theCollection" ), + cb.literal( "xyz" ) + ), cb.collectionContainsNullable( root.get( "theCollection" ), "xyz" ), cb.collectionContainsNullable( List.of( "abc", "xyz" ), cb.literal( "xyz" ) ) ); @@ -137,7 +150,10 @@ public void testNodeBuilderCollection(SessionFactoryScope scope) { public void testContainsSyntax(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-array-contains-hql-example[] - List results = em.createQuery( "from EntityWithArrays e where e.theArray contains 'abc'", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where e.theArray contains 'abc'", + EntityWithArrays.class + ) .getResultList(); //end::hql-array-contains-hql-example[] assertEquals( 1, results.size() ); @@ -149,7 +165,10 @@ public void testContainsSyntax(SessionFactoryScope scope) { public void testInSyntax(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-array-in-hql-example[] - List results = em.createQuery( "from EntityWithArrays e where 'abc' in e.theArray", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where 'abc' in e.theArray", + EntityWithArrays.class + ) .getResultList(); //end::hql-array-in-hql-example[] assertEquals( 1, results.size() ); @@ -158,7 +177,7 @@ public void testInSyntax(SessionFactoryScope scope) { } @Test - @JiraKey( "HHH-18851" ) + @JiraKey("HHH-18851") public void testInArray(SessionFactoryScope scope) { scope.inSession( em -> { List results = em.createQuery( diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayGetTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayGetTest.java index c1bfe8674881..e9a2bf986ed6 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayGetTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayGetTest.java @@ -6,6 +6,7 @@ import java.util.List; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.sqm.NodeBuilder; @@ -17,6 +18,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -30,7 +32,7 @@ */ @DomainModel(annotatedClasses = EntityWithArrays.class) @SessionFactory -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsStructuralArrays.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsStructuralArrays.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsArrayGet.class) // Clear the type cache, otherwise we might run into ORA-21700: object does not exist or is marked for delete @BootstrapServiceRegistry(integrators = SharedDriverManagerTypeCacheClearingIntegrator.class) @@ -39,8 +41,8 @@ public class ArrayGetTest { @BeforeEach public void prepareData(SessionFactoryScope scope) { scope.inTransaction( em -> { - em.persist( new EntityWithArrays( 1L, new String[]{} ) ); - em.persist( new EntityWithArrays( 2L, new String[]{ "abc", null, "def" } ) ); + em.persist( new EntityWithArrays( 1L, new String[] {} ) ); + em.persist( new EntityWithArrays( 2L, new String[] { "abc", null, "def" } ) ); em.persist( new EntityWithArrays( 3L, null ) ); } ); } @@ -56,7 +58,10 @@ public void cleanup(SessionFactoryScope scope) { public void testGet(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-array-get-example[] - List results = em.createQuery( "from EntityWithArrays e where array_get(e.theArray, 1) = 'abc'", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where array_get(e.theArray, 1) = 'abc'", + EntityWithArrays.class + ) .getResultList(); //end::hql-array-get-example[] assertEquals( 1, results.size() ); @@ -65,9 +70,13 @@ public void testGet(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testGetNullElement(SessionFactoryScope scope) { scope.inSession( em -> { - List results = em.createQuery( "from EntityWithArrays e where array_length(e.theArray) >= 2 and array_get(e.theArray, 2) is null", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where array_length(e.theArray) >= 2 and array_get(e.theArray, 2) is null", + EntityWithArrays.class + ) .getResultList(); assertEquals( 1, results.size() ); assertEquals( 2L, results.get( 0 ).getId() ); @@ -77,7 +86,10 @@ public void testGetNullElement(SessionFactoryScope scope) { @Test public void testGetNotExisting(SessionFactoryScope scope) { scope.inSession( em -> { - List results = em.createQuery( "from EntityWithArrays e where array_get(e.theArray,100) is null", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where array_get(e.theArray,100) is null", + EntityWithArrays.class + ) .getResultList(); assertEquals( 3, results.size() ); } ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayLengthTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayLengthTest.java index 10e33f313774..b5f326281fc1 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayLengthTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayLengthTest.java @@ -6,6 +6,7 @@ import java.util.List; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.sqm.NodeBuilder; @@ -17,6 +18,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -30,7 +32,7 @@ */ @DomainModel(annotatedClasses = EntityWithArrays.class) @SessionFactory -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsStructuralArrays.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsStructuralArrays.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsArrayLength.class) // Clear the type cache, otherwise we might run into ORA-21700: object does not exist or is marked for delete @BootstrapServiceRegistry(integrators = SharedDriverManagerTypeCacheClearingIntegrator.class) @@ -39,8 +41,8 @@ public class ArrayLengthTest { @BeforeEach public void prepareData(SessionFactoryScope scope) { scope.inTransaction( em -> { - em.persist( new EntityWithArrays( 1L, new String[]{} ) ); - em.persist( new EntityWithArrays( 2L, new String[]{ "abc", null, "def" } ) ); + em.persist( new EntityWithArrays( 1L, new String[] {} ) ); + em.persist( new EntityWithArrays( 2L, new String[] { "abc", null, "def" } ) ); em.persist( new EntityWithArrays( 3L, null ) ); } ); } @@ -53,10 +55,14 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testLengthZero(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-array-length-example[] - List results = em.createQuery( "from EntityWithArrays e where array_length(e.theArray) = 0", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where array_length(e.theArray) = 0", + EntityWithArrays.class + ) .getResultList(); //end::hql-array-length-example[] assertEquals( 1, results.size() ); @@ -65,9 +71,13 @@ public void testLengthZero(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testLengthThree(SessionFactoryScope scope) { scope.inSession( em -> { - List results = em.createQuery( "from EntityWithArrays e where array_length(e.theArray) = 3", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where array_length(e.theArray) = 3", + EntityWithArrays.class + ) .getResultList(); assertEquals( 1, results.size() ); assertEquals( 2L, results.get( 0 ).getId() ); @@ -75,9 +85,13 @@ public void testLengthThree(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testLengthNull(SessionFactoryScope scope) { scope.inSession( em -> { - List results = em.createQuery( "from EntityWithArrays e where array_length(e.theArray) is null", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where array_length(e.theArray) is null", + EntityWithArrays.class + ) .getResultList(); assertEquals( 1, results.size() ); assertEquals( 3L, results.get( 0 ).getId() ); @@ -85,6 +99,7 @@ public void testLengthNull(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNodeBuilderArray(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -99,6 +114,7 @@ public void testNodeBuilderArray(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNodeBuilderCollection(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -113,10 +129,14 @@ public void testNodeBuilderCollection(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testLengthThreeHql(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-array-length-hql-example[] - List results = em.createQuery( "from EntityWithArrays e where length(e.theArray) = 3", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where length(e.theArray) = 3", + EntityWithArrays.class + ) .getResultList(); //end::hql-array-length-hql-example[] assertEquals( 1, results.size() ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayPositionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayPositionTest.java index 539411c6f8b2..c0273958d9b2 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayPositionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayPositionTest.java @@ -7,6 +7,7 @@ import java.util.Collection; import java.util.List; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.sqm.NodeBuilder; @@ -19,6 +20,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -32,7 +34,7 @@ */ @DomainModel(annotatedClasses = EntityWithArrays.class) @SessionFactory -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsStructuralArrays.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsStructuralArrays.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsArrayPosition.class) // Clear the type cache, otherwise we might run into ORA-21700: object does not exist or is marked for delete @BootstrapServiceRegistry(integrators = SharedDriverManagerTypeCacheClearingIntegrator.class) @@ -41,8 +43,8 @@ public class ArrayPositionTest { @BeforeEach public void prepareData(SessionFactoryScope scope) { scope.inTransaction( em -> { - em.persist( new EntityWithArrays( 1L, new String[]{} ) ); - em.persist( new EntityWithArrays( 2L, new String[]{ "abc", null, "def" } ) ); + em.persist( new EntityWithArrays( 1L, new String[] {} ) ); + em.persist( new EntityWithArrays( 2L, new String[] { "abc", null, "def" } ) ); em.persist( new EntityWithArrays( 3L, null ) ); } ); } @@ -55,10 +57,14 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testPosition(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-array-position-example[] - List results = em.createQuery( "from EntityWithArrays e where array_position(e.theArray, 'abc') = 1", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where array_position(e.theArray, 'abc') = 1", + EntityWithArrays.class + ) .getResultList(); //end::hql-array-position-example[] assertEquals( 1, results.size() ); @@ -67,18 +73,26 @@ public void testPosition(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.gaussdb has different behavior") public void testPositionZero(SessionFactoryScope scope) { scope.inSession( em -> { - List results = em.createQuery( "from EntityWithArrays e where array_position(e.theArray, 'xyz') = 0", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where array_position(e.theArray, 'xyz') = 0", + EntityWithArrays.class + ) .getResultList(); assertEquals( 2, results.size() ); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testPositionNull(SessionFactoryScope scope) { scope.inSession( em -> { - List results = em.createQuery( "from EntityWithArrays e where array_position(e.theArray, null) = 2", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where array_position(e.theArray, null) = 2", + EntityWithArrays.class + ) .getResultList(); assertEquals( 1, results.size() ); assertEquals( 2L, results.get( 0 ).getId() ); @@ -87,14 +101,19 @@ public void testPositionNull(SessionFactoryScope scope) { @Test @Jira("https://hibernate.atlassian.net/browse/HHH-17801") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testEnumPosition(SessionFactoryScope scope) { scope.inSession( em -> { - em.createQuery( "from EntityWithArrays e where array_position(e.theLabels, e.theLabel) > 0", EntityWithArrays.class ) + em.createQuery( + "from EntityWithArrays e where array_position(e.theLabels, e.theLabel) > 0", + EntityWithArrays.class + ) .getResultList(); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNodeBuilderArray(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -114,6 +133,7 @@ public void testNodeBuilderArray(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNodeBuilderCollection(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -133,10 +153,14 @@ public void testNodeBuilderCollection(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testPositionOverload(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-array-position-hql-example[] - List results = em.createQuery( "from EntityWithArrays e where position('abc' in e.theArray) = 1", EntityWithArrays.class ) + List results = em.createQuery( + "from EntityWithArrays e where position('abc' in e.theArray) = 1", + EntityWithArrays.class + ) .getResultList(); //end::hql-array-position-hql-example[] assertEquals( 1, results.size() ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayTrimTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayTrimTest.java index 1e98a094563c..5c6e94c2476c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayTrimTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayTrimTest.java @@ -9,6 +9,7 @@ import java.util.List; import org.hibernate.dialect.CockroachDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaRoot; @@ -88,6 +89,7 @@ public void testTrimAll(SessionFactoryScope scope) { @Test @SkipForDialect(dialectClass = PostgreSQLDialect.class, majorVersion = 13, matchSubTypes = true, reason = "The PostgreSQL emulation for version < 14 doesn't throw an error") @SkipForDialect(dialectClass = CockroachDialect.class, reason = "The Cockroach emulation doesn't throw an error") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.gaussdb has different behavior") public void testTrimOutOfRange(SessionFactoryScope scope) { scope.inSession( em -> { try { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayUnnestStructTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayUnnestStructTest.java index b1fb210f29c2..70cf8bb9bbec 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayUnnestStructTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayUnnestStructTest.java @@ -8,6 +8,7 @@ import java.util.List; import org.hibernate.annotations.Struct; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.SybaseASEDialect; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaFunctionJoin; @@ -74,6 +75,7 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.do not support") public void testUnnest(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-array-unnest-aggregate-example[] @@ -104,6 +106,7 @@ public void testUnnest(SessionFactoryScope scope) { @Test @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "xmltable can't be used with a left join") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.do not support") public void testNodeBuilderUnnest(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -143,6 +146,7 @@ public void testNodeBuilderUnnest(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.do not support") public void testUnnestOrdinality(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-array-unnest-aggregate-with-ordinality-example[] @@ -166,6 +170,7 @@ public void testUnnestOrdinality(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.do not support") public void testNodeBuilderUnnestOrdinality(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayUnnestTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayUnnestTest.java index eae4e53a0ae8..347af1bf2767 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayUnnestTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayUnnestTest.java @@ -6,6 +6,7 @@ import java.util.List; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.SybaseASEDialect; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaFunctionJoin; @@ -59,6 +60,7 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testUnnest(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-array-unnest-example[] @@ -84,6 +86,7 @@ public void testUnnest(SessionFactoryScope scope) { @Test @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "xmltable can't be used with a left join") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testNodeBuilderUnnest(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -112,6 +115,7 @@ public void testNodeBuilderUnnest(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testUnnestOrdinality(SessionFactoryScope scope) { scope.inSession( em -> { List results = em.createQuery( @@ -141,6 +145,7 @@ public void testUnnestOrdinality(SessionFactoryScope scope) { @Test @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "xmltable can't be used with a left join") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testNodeBuilderUnnestOrdinality(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayAggregateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayAggregateTest.java index e476ce50cecc..913ae142445c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayAggregateTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayAggregateTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.json; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -14,6 +15,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -22,10 +24,11 @@ @DomainModel(standardModels = StandardDomainModel.GAMBIT) @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonArrayAgg.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonArrayAgg.class) public class JsonArrayAggregateTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-arrayagg-example[] @@ -35,6 +38,7 @@ public void testSimple(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNull(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-arrayagg-null-example[] @@ -44,6 +48,7 @@ public void testNull(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testOrderBy(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-arrayagg-order-by-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayInsertTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayInsertTest.java index bebd3c0c5da8..43ab5a8e86f6 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayInsertTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayInsertTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.json; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -14,6 +15,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -22,10 +24,11 @@ @DomainModel(standardModels = StandardDomainModel.GAMBIT) @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonInsert.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonInsert.class) public class JsonArrayInsertTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-array-insert-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayTest.java index e957865bc63f..a68507bfd5d8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayTest.java @@ -5,7 +5,9 @@ package org.hibernate.orm.test.function.json; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.RequiresDialectFeature; @@ -13,6 +15,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -21,10 +24,12 @@ @DomainModel @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonArray.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonArray.class) +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class JsonArrayTest { @Test + @SkipForDialect( dialectClass = GaussDBDialect.class) public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-array-example[] @@ -34,10 +39,11 @@ public void testSimple(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testNullClause(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-array-on-null-example[] - em.createQuery("select json_array(null, 1 null on null)" ).getResultList(); + em.createQuery( "select json_array(null, 1 null on null)" ).getResultList(); //end::hql-json-array-on-null-example[] } ); } @@ -45,7 +51,7 @@ public void testNullClause(SessionFactoryScope scope) { @Test public void testAbsentOnNull(SessionFactoryScope scope) { scope.inSession( em -> { - em.createQuery("select json_array(null, 1 absent on null)" ).getResultList(); + em.createQuery( "select json_array(null, 1 absent on null)" ).getResultList(); } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayUnnestTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayUnnestTest.java index 53dda94e619e..cd77cd567455 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayUnnestTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonArrayUnnestTest.java @@ -8,11 +8,13 @@ import java.util.List; import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaFunctionJoin; import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.tree.SqmJoinType; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.hibernate.type.SqlTypes; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -69,6 +71,7 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testUnnest(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-array-unnest-aggregate-example[] @@ -98,6 +101,7 @@ public void testUnnest(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testNodeBuilderUnnest(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -137,6 +141,7 @@ public void testNodeBuilderUnnest(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testUnnestOrdinality(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-array-unnest-aggregate-with-ordinality-example[] @@ -160,6 +165,7 @@ public void testUnnestOrdinality(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testNodeBuilderUnnestOrdinality(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonExistsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonExistsTest.java index 14cbdf60f675..5cb9cd620192 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonExistsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonExistsTest.java @@ -10,6 +10,7 @@ import org.hibernate.HibernateException; import org.hibernate.JDBCException; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.MariaDBDialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.sql.exec.ExecutionException; @@ -35,7 +36,7 @@ @DomainModel(annotatedClasses = EntityWithJson.class) @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonExists.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonExists.class) public class JsonExistsTest { @BeforeEach @@ -50,7 +51,7 @@ public void prepareData(SessionFactoryScope scope) { entity.getJson().put( "theNull", null ); entity.getJson().put( "theArray", new String[] { "a", "b", "c" } ); entity.getJson().put( "theObject", new HashMap<>( entity.getJson() ) ); - em.persist(entity); + em.persist( entity ); } ); } @@ -62,10 +63,14 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-exists-example[] - List results = em.createQuery( "select json_exists(e.json, '$.theString') from EntityWithJson e", Boolean.class ) + List results = em.createQuery( + "select json_exists(e.json, '$.theString') from EntityWithJson e", + Boolean.class + ) .getResultList(); //end::hql-json-exists-example[] assertEquals( 1, results.size() ); @@ -74,10 +79,14 @@ public void testSimple(SessionFactoryScope scope) { @Test @SkipForDialect(dialectClass = OracleDialect.class, majorVersion = 21, matchSubTypes = true, reason = "Oracle bug in versions before 23") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testPassing(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-exists-passing-example[] - List results = em.createQuery( "select json_exists(e.json, '$.theArray[$idx]' passing 1 as idx) from EntityWithJson e", Boolean.class ) + List results = em.createQuery( + "select json_exists(e.json, '$.theArray[$idx]' passing 1 as idx) from EntityWithJson e", + Boolean.class + ) .getResultList(); //end::hql-json-exists-passing-example[] assertEquals( 1, results.size() ); @@ -90,12 +99,12 @@ public void testOnError(SessionFactoryScope scope) { scope.inSession( em -> { try { //tag::hql-json-exists-on-error-example[] - em.createQuery( "select json_exists('invalidJson', '$.theInt' error on error) from EntityWithJson e") + em.createQuery( "select json_exists('invalidJson', '$.theInt' error on error) from EntityWithJson e" ) .getResultList(); //end::hql-json-exists-on-error-example[] - fail("error clause should fail because of invalid json document"); + fail( "error clause should fail because of invalid json document" ); } - catch ( HibernateException e ) { + catch (HibernateException e) { if ( !( e instanceof JDBCException ) && !( e instanceof ExecutionException ) ) { throw e; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonInsertTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonInsertTest.java index 1e9a53f025e2..2eed3326dce5 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonInsertTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonInsertTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.json; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -14,6 +15,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -22,10 +24,11 @@ @DomainModel(standardModels = StandardDomainModel.GAMBIT) @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonInsert.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonInsert.class) public class JsonInsertTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-insert-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonMergepatchTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonMergepatchTest.java index 5d4cef99f3dd..2dbe3670f4eb 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonMergepatchTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonMergepatchTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.json; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -14,6 +15,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -22,10 +24,11 @@ @DomainModel(standardModels = StandardDomainModel.GAMBIT) @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonMergepatch.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonMergepatch.class) public class JsonMergepatchTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-mergepatch-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonObjectAggregateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonObjectAggregateTest.java index 7436b94c1175..b9338c5e9f0a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonObjectAggregateTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonObjectAggregateTest.java @@ -7,6 +7,7 @@ import org.hibernate.cfg.QuerySettings; import org.hibernate.dialect.CockroachDialect; import org.hibernate.dialect.DB2Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.PostgreSQLDialect; @@ -33,6 +34,7 @@ public class JsonObjectAggregateTest { @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-objectagg-example[] @@ -42,6 +44,7 @@ public void testSimple(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testNull(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-objectagg-null-example[] @@ -57,6 +60,7 @@ public void testNull(SessionFactoryScope scope) { @SkipForDialect(dialectClass = DB2Dialect.class, reason = "DB2 has no way to throw an error on duplicate json object keys.") @SkipForDialect(dialectClass = CockroachDialect.class, reason = "CockroachDB has no way to throw an error on duplicate json object keys.") @SkipForDialect(dialectClass = PostgreSQLDialect.class, majorVersion = 15, matchSubTypes = true, reason = "CockroachDB has no way to throw an error on duplicate json object keys.") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testUniqueKeys(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-objectagg-unique-keys-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonObjectTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonObjectTest.java index 4164d137f668..71bc53167e19 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonObjectTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonObjectTest.java @@ -6,6 +6,7 @@ import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.RequiresDialectFeature; @@ -13,6 +14,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -25,6 +27,7 @@ public class JsonObjectTest { @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-object-example[] @@ -34,6 +37,7 @@ public void testSimple(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testNullClause(SessionFactoryScope scope) { scope.inSession( em -> { em.createQuery("select json_object('key': null null on null)" ).getResultList(); @@ -41,6 +45,7 @@ public void testNullClause(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testAbsentOnNull(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-object-on-null-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonQueryTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonQueryTest.java index ed47894dbe18..93e6ea88a606 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonQueryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonQueryTest.java @@ -10,6 +10,7 @@ import org.hibernate.HibernateException; import org.hibernate.JDBCException; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.MariaDBDialect; import org.hibernate.sql.exec.ExecutionException; @@ -36,7 +37,7 @@ @DomainModel(annotatedClasses = EntityWithJson.class) @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonQuery.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonQuery.class) public class JsonQueryTest { @BeforeEach @@ -51,7 +52,7 @@ public void prepareData(SessionFactoryScope scope) { entity.getJson().put( "theNull", null ); entity.getJson().put( "theArray", new String[] { "a", "b", "c" } ); entity.getJson().put( "theObject", new HashMap<>( entity.getJson() ) ); - em.persist(entity); + em.persist( entity ); } ); } @@ -63,10 +64,14 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-query-example[] - List results = em.createQuery( "select json_query(e.json, '$.theString') from EntityWithJson e", Tuple.class ) + List results = em.createQuery( + "select json_query(e.json, '$.theString') from EntityWithJson e", + Tuple.class + ) .getResultList(); //end::hql-json-query-example[] assertEquals( 1, results.size() ); @@ -74,10 +79,14 @@ public void testSimple(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testPassing(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-query-passing-example[] - List results = em.createQuery( "select json_query(e.json, '$.theArray[$idx]' passing 1 as idx) from EntityWithJson e", Tuple.class ) + List results = em.createQuery( + "select json_query(e.json, '$.theArray[$idx]' passing 1 as idx) from EntityWithJson e", + Tuple.class + ) .getResultList(); //end::hql-json-query-passing-example[] assertEquals( 1, results.size() ); @@ -85,10 +94,14 @@ public void testPassing(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testWithWrapper(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-query-with-wrapper-example[] - List results = em.createQuery( "select json_query(e.json, '$.theInt' with wrapper) from EntityWithJson e", Tuple.class ) + List results = em.createQuery( + "select json_query(e.json, '$.theInt' with wrapper) from EntityWithJson e", + Tuple.class + ) .getResultList(); //end::hql-json-query-with-wrapper-example[] assertEquals( 1, results.size() ); @@ -101,12 +114,12 @@ public void testOnError(SessionFactoryScope scope) { scope.inSession( em -> { try { //tag::hql-json-query-on-error-example[] - em.createQuery( "select json_query('invalidJson', '$.theInt' error on error) from EntityWithJson e") + em.createQuery( "select json_query('invalidJson', '$.theInt' error on error) from EntityWithJson e" ) .getResultList(); //end::hql-json-query-on-error-example[] - fail("error clause should fail because of invalid json document"); + fail( "error clause should fail because of invalid json document" ); } - catch ( HibernateException e ) { + catch (HibernateException e) { if ( !( e instanceof JDBCException ) && !( e instanceof ExecutionException ) ) { throw e; } @@ -115,17 +128,19 @@ public void testOnError(SessionFactoryScope scope) { } @Test - @RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonValueErrorBehavior.class) + @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonValueErrorBehavior.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testOnEmpty(SessionFactoryScope scope) { scope.inSession( em -> { try { //tag::hql-json-query-on-empty-example[] - em.createQuery("select json_query(e.json, '$.nonExisting' error on empty error on error) from EntityWithJson e" ) + em.createQuery( + "select json_query(e.json, '$.nonExisting' error on empty error on error) from EntityWithJson e" ) .getResultList(); //end::hql-json-query-on-empty-example[] - fail("empty clause should fail because of json path doesn't produce results"); + fail( "empty clause should fail because of json path doesn't produce results" ); } - catch ( HibernateException e ) { + catch (HibernateException e) { if ( !( e instanceof JDBCException ) && !( e instanceof ExecutionException ) ) { throw e; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonRemoveTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonRemoveTest.java index f6c372faba9e..6ac109ced69a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonRemoveTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonRemoveTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.json; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -14,6 +15,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -22,10 +24,11 @@ @DomainModel(standardModels = StandardDomainModel.GAMBIT) @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonRemove.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonRemove.class) public class JsonRemoveTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-remove-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonReplaceTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonReplaceTest.java index 1bdebfca12ea..02173340bf58 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonReplaceTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonReplaceTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.json; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -14,6 +15,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -22,10 +24,11 @@ @DomainModel(standardModels = StandardDomainModel.GAMBIT) @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonReplace.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonReplace.class) public class JsonReplaceTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-replace-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonSetTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonSetTest.java index 40eedca52978..f4ce6630ed5d 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonSetTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonSetTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.json; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -14,6 +15,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -22,10 +24,11 @@ @DomainModel(standardModels = StandardDomainModel.GAMBIT) @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonSet.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonSet.class) public class JsonSetTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-set-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonTableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonTableTest.java index 1ed0e8f7d86e..0b1d7e455ead 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonTableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonTableTest.java @@ -4,16 +4,20 @@ */ package org.hibernate.orm.test.function.json; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.persistence.Tuple; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.criteria.JpaFunctionJoin; import org.hibernate.query.criteria.JpaJsonTableColumnsNode; import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.tree.expression.SqmJsonTableFunction; import org.hibernate.query.sqm.tree.select.SqmSelectStatement; + import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.RequiresDialectFeature; @@ -21,14 +25,14 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +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; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.persistence.Tuple; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -54,7 +58,7 @@ public void prepareData(SessionFactoryScope scope) { entity.getJson().put( "theNull", null ); entity.getJson().put( "theArray", new String[] { "a", "b", "c" } ); entity.getJson().put( "theObject", new HashMap<>( entity.getJson() ) ); - em.persist(entity); + em.persist( entity ); } ); } @@ -66,6 +70,7 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not support json_table") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-table-example[] @@ -114,6 +119,7 @@ join lateral json_table(e.json,'$' columns( } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not support json_table") public void testNodeBuilderJsonTableObject(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -162,6 +168,7 @@ public void testNodeBuilderJsonTableObject(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not support json_table") public void testArray(SessionFactoryScope scope) { scope.inSession( em -> { final String query = """ @@ -183,6 +190,7 @@ from json_table('[1,2]','$[*]' columns(val Integer path '$', idx for ordinality) } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not support json_table") public void testArrayParam(SessionFactoryScope scope) { scope.inSession( em -> { final String query = """ diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonValueTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonValueTest.java index 6a18e2662901..e80571f59a2c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonValueTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/json/JsonValueTest.java @@ -10,6 +10,7 @@ import org.hibernate.HibernateException; import org.hibernate.JDBCException; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.MariaDBDialect; import org.hibernate.sql.exec.ExecutionException; @@ -36,7 +37,7 @@ @DomainModel(annotatedClasses = EntityWithJson.class) @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonValue.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonValue.class) public class JsonValueTest { @BeforeEach @@ -51,7 +52,7 @@ public void prepareData(SessionFactoryScope scope) { entity.getJson().put( "theNull", null ); entity.getJson().put( "theArray", new String[] { "a", "b", "c" } ); entity.getJson().put( "theObject", new HashMap<>( entity.getJson() ) ); - em.persist(entity); + em.persist( entity ); } ); } @@ -63,10 +64,14 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-value-example[] - List results = em.createQuery( "select json_value(e.json, '$.theString') from EntityWithJson e", Tuple.class ) + List results = em.createQuery( + "select json_value(e.json, '$.theString') from EntityWithJson e", + Tuple.class + ) .getResultList(); //end::hql-json-value-example[] assertEquals( 1, results.size() ); @@ -74,10 +79,14 @@ public void testSimple(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testPassing(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-value-passing-example[] - List results = em.createQuery( "select json_value(e.json, '$.theArray[$idx]' passing 1 as idx) from EntityWithJson e", Tuple.class ) + List results = em.createQuery( + "select json_value(e.json, '$.theArray[$idx]' passing 1 as idx) from EntityWithJson e", + Tuple.class + ) .getResultList(); //end::hql-json-value-passing-example[] assertEquals( 1, results.size() ); @@ -85,10 +94,14 @@ public void testPassing(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testReturning(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-json-value-returning-example[] - List results = em.createQuery( "select json_value(e.json, '$.theInt' returning Integer) from EntityWithJson e", Tuple.class ) + List results = em.createQuery( + "select json_value(e.json, '$.theInt' returning Integer) from EntityWithJson e", + Tuple.class + ) .getResultList(); //end::hql-json-value-returning-example[] assertEquals( 1, results.size() ); @@ -101,12 +114,12 @@ public void testOnError(SessionFactoryScope scope) { scope.inSession( em -> { try { //tag::hql-json-value-on-error-example[] - em.createQuery( "select json_value('invalidJson', '$.theInt' error on error) from EntityWithJson e") + em.createQuery( "select json_value('invalidJson', '$.theInt' error on error) from EntityWithJson e" ) .getResultList(); //end::hql-json-value-on-error-example[] - fail("error clause should fail because of invalid json document"); + fail( "error clause should fail because of invalid json document" ); } - catch ( HibernateException e ) { + catch (HibernateException e) { if ( !( e instanceof JDBCException ) && !( e instanceof ExecutionException ) ) { throw e; } @@ -115,17 +128,19 @@ public void testOnError(SessionFactoryScope scope) { } @Test - @RequiresDialectFeature( feature = DialectFeatureChecks.SupportsJsonValueErrorBehavior.class) + @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonValueErrorBehavior.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testOnEmpty(SessionFactoryScope scope) { scope.inSession( em -> { try { //tag::hql-json-value-on-empty-example[] - em.createQuery("select json_value(e.json, '$.nonExisting' error on empty error on error) from EntityWithJson e" ) + em.createQuery( + "select json_value(e.json, '$.nonExisting' error on empty error on error) from EntityWithJson e" ) .getResultList(); //end::hql-json-value-on-empty-example[] - fail("empty clause should fail because of json path doesn't produce results"); + fail( "empty clause should fail because of json path doesn't produce results" ); } - catch ( HibernateException e ) { + catch (HibernateException e) { if ( !( e instanceof JDBCException ) && !( e instanceof ExecutionException ) ) { throw e; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/srf/GenerateSeriesTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/srf/GenerateSeriesTest.java index 0b3f894a5a14..12faf55d8554 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/srf/GenerateSeriesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/srf/GenerateSeriesTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.srf; import jakarta.persistence.Tuple; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.SybaseASEDialect; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaFunctionRoot; @@ -80,6 +81,7 @@ public void testNodeBuilderGenerateSeries(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.not support index") public void testGenerateSeriesOrdinality(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-set-returning-function-generate-series-ordinality-example[] @@ -99,6 +101,7 @@ public void testGenerateSeriesOrdinality(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.not support index") public void testNodeBuilderGenerateSeriesOrdinality(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -133,6 +136,7 @@ public void testGenerateTimeSeries(SessionFactoryScope scope) { @Test @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "Sybase bug?") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.not support index") public void testGenerateSeriesCorrelation(SessionFactoryScope scope) { scope.inSession( em -> { List resultList = em.createQuery( @@ -166,6 +170,7 @@ public void testGenerateSeriesNoProgression(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.not support index") public void testGenerateSeriesNoProgressionOrdinality(SessionFactoryScope scope) { scope.inSession( em -> { List resultList = em.createQuery( "select index(e), e from generate_series(2, 1, 1) e", Tuple.class ) diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlAggTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlAggTest.java index ba85efb5898c..4c8f617aa548 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlAggTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlAggTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.xml; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -14,6 +15,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -22,14 +24,16 @@ @DomainModel(standardModels = StandardDomainModel.GAMBIT) @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.XML_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsXmlagg.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlagg.class) public class XmlAggTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xmlagg-example[] - em.createQuery( "select xmlagg(xmlelement(name a, e.theString) order by e.id) from EntityOfBasics e" ).getResultList(); + em.createQuery( "select xmlagg(xmlelement(name a, e.theString) order by e.id) from EntityOfBasics e" ) + .getResultList(); //end::hql-xmlagg-example[] } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlArrayUnnestTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlArrayUnnestTest.java index 88c35484428f..3895c87aa8b8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlArrayUnnestTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlArrayUnnestTest.java @@ -11,6 +11,7 @@ import jakarta.persistence.Tuple; import jakarta.persistence.criteria.Nulls; import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.SybaseASEDialect; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaFunctionJoin; @@ -69,6 +70,7 @@ public void cleanup(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testUnnest(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xml-array-unnest-aggregate-example[] @@ -98,6 +100,7 @@ public void testUnnest(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testNodeBuilderUnnest(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -137,6 +140,7 @@ public void testNodeBuilderUnnest(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testUnnestOrdinality(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xml-array-unnest-aggregate-with-ordinality-example[] @@ -161,6 +165,7 @@ public void testUnnestOrdinality(SessionFactoryScope scope) { @Test @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "xmltable can't be used with a left join") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void testNodeBuilderUnnestOrdinality(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlCommentTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlCommentTest.java index 7a3834c1aa70..be09d70c59ad 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlCommentTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlCommentTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.xml; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; @@ -13,6 +14,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -21,10 +23,11 @@ @DomainModel @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.XML_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsXmlcomment.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlcomment.class) public class XmlCommentTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xmlcomment-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlConcatTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlConcatTest.java index b0abfacf84db..b5e098e5110a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlConcatTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlConcatTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.xml; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; @@ -13,6 +14,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -21,10 +23,11 @@ @DomainModel @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.XML_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsXmlconcat.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlconcat.class) public class XmlConcatTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xmlconcat-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlElementTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlElementTest.java index 5909ba748dd2..7f2e73d7352c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlElementTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlElementTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.xml; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; @@ -13,6 +14,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -21,10 +23,11 @@ @DomainModel @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.XML_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsXmlelement.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlelement.class) public class XmlElementTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xmlelement-example[] @@ -34,10 +37,13 @@ public void testSimple(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testAttributesAndContent(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xmlelement-attributes-content-example[] - em.createQuery("select xmlelement(name `my-element`, xmlattributes(123 as attr1, '456' as `attr-2`), 'myContent', xmlelement(name empty))" ).getResultList(); + em.createQuery( + "select xmlelement(name `my-element`, xmlattributes(123 as attr1, '456' as `attr-2`), 'myContent', xmlelement(name empty))" ) + .getResultList(); //end::hql-xmlelement-attributes-content-example[] } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlExistsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlExistsTest.java index eae59c692b39..1654206bc015 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlExistsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlExistsTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.xml; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; @@ -13,6 +14,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -21,10 +23,11 @@ @DomainModel @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.XML_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsXmlexists.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlexists.class) public class XmlExistsTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xmlexists-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlForestTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlForestTest.java index d28e14e1e08d..a6ff723d84e0 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlForestTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlForestTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.xml; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; @@ -13,6 +14,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -21,10 +23,11 @@ @DomainModel @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.XML_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsXmlforest.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlforest.class) public class XmlForestTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xmlforest-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlPiTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlPiTest.java index 790df66d0d48..b13270e77d17 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlPiTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlPiTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.xml; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; @@ -13,6 +14,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -21,10 +23,11 @@ @DomainModel @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.XML_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsXmlpi.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlpi.class) public class XmlPiTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xmlpi-example[] @@ -34,10 +37,11 @@ public void testSimple(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testContent(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xmlpi-content-example[] - em.createQuery("select xmlpi(name `php`, 'echo \"test\"')" ).getResultList(); + em.createQuery( "select xmlpi(name `php`, 'echo \"test\"')" ).getResultList(); //end::hql-xmlpi-content-example[] } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlQueryTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlQueryTest.java index 4861f7e6f600..740143c9c8e2 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlQueryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlQueryTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.function.xml; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; @@ -13,6 +14,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; /** @@ -21,10 +23,11 @@ @DomainModel @SessionFactory @ServiceRegistry(settings = @Setting(name = QuerySettings.XML_FUNCTIONS_ENABLED, value = "true")) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsXmlquery.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlquery.class) public class XmlQueryTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xmlquery-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlTableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlTableTest.java index d8741776af48..595c5e404ab7 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlTableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/xml/XmlTableTest.java @@ -9,6 +9,7 @@ import jakarta.persistence.Tuple; import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.SybaseASEDialect; @@ -115,6 +116,7 @@ public void cleanupData(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resoving.not support") public void testSimple(SessionFactoryScope scope) { scope.inSession( em -> { //tag::hql-xml-table-example[] @@ -156,6 +158,7 @@ from xmltable('/root/elem' passing :xml columns @Test @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "Sybase ASE needs a special emulation for query columns that is impossible with parameters") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resoving.not support") public void testNodeBuilderXmlTableObject(SessionFactoryScope scope) { scope.inSession( em -> { final NodeBuilder cb = (NodeBuilder) em.getCriteriaBuilder(); @@ -194,6 +197,7 @@ public void testNodeBuilderXmlTableObject(SessionFactoryScope scope) { @Test @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "Sybase doesn't support such xpath expressions directly in xmltable. We could emulate that through generating xmlextract calls though") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resoving.not support") public void testCorrelateXmlTable(SessionFactoryScope scope) { scope.inSession( em -> { final String query = """ diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/generatedkeys/identity/IdentityGeneratedKeysTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/generatedkeys/identity/IdentityGeneratedKeysTest.java index 5403dd91a429..df05095bc017 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/generatedkeys/identity/IdentityGeneratedKeysTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/generatedkeys/identity/IdentityGeneratedKeysTest.java @@ -4,17 +4,19 @@ */ package org.hibernate.orm.test.generatedkeys.identity; -import jakarta.persistence.PersistenceException; -import jakarta.persistence.TransactionRequiredException; - -import org.junit.Test; - import org.hibernate.Session; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.testing.orm.junit.SkipForDialect; +import org.junit.Test; + +import jakarta.persistence.PersistenceException; +import jakarta.persistence.TransactionRequiredException; import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; import static org.junit.Assert.assertEquals; @@ -25,7 +27,7 @@ /** * @author Steve Ebersole */ -@RequiresDialectFeature( DialectChecks.SupportsIdentityColumns.class ) +@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class) public class IdentityGeneratedKeysTest extends BaseCoreFunctionalTestCase { @Override @@ -45,11 +47,12 @@ public String[] getMappings() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testIdentityColumnGeneratedIds() { Session s = openSession(); s.beginTransaction(); MyEntity myEntity = new MyEntity( "test" ); - s.persist(myEntity); + s.persist( myEntity ); assertNotNull( "identity column did not force immediate insert", myEntity.getId() ); s.remove( myEntity ); s.getTransaction().commit(); @@ -63,14 +66,18 @@ public void testPersistOutsideTransaction() { long initialInsertCount = sessionFactory().getStatistics().getEntityInsertCount(); MyEntity myEntity2 = new MyEntity( "test-persist" ); s.persist( myEntity2 ); - assertEquals( "persist on identity column not delayed", initialInsertCount, sessionFactory().getStatistics().getEntityInsertCount() ); + assertEquals( + "persist on identity column not delayed", + initialInsertCount, + sessionFactory().getStatistics().getEntityInsertCount() + ); assertNull( myEntity2.getId() ); // an explicit flush should cause execution of the delayed insertion s.flush(); fail( "TransactionRequiredException required upon flush" ); } - catch ( PersistenceException ex ) { + catch (PersistenceException ex) { // expected assertTyping( TransactionRequiredException.class, ex ); } @@ -80,7 +87,7 @@ public void testPersistOutsideTransaction() { } @Test - @SuppressWarnings( {"unchecked"}) + @SuppressWarnings({ "unchecked" }) public void testPersistOutsideTransactionCascadedToNonInverseCollection() { long initialInsertCount = sessionFactory().getStatistics().getEntityInsertCount(); Session s = openSession(); @@ -88,12 +95,16 @@ public void testPersistOutsideTransactionCascadedToNonInverseCollection() { MyEntity myEntity = new MyEntity( "test-persist" ); myEntity.getNonInverseChildren().add( new MyChild( "test-child-persist-non-inverse" ) ); s.persist( myEntity ); - assertEquals( "persist on identity column not delayed", initialInsertCount, sessionFactory().getStatistics().getEntityInsertCount() ); + assertEquals( + "persist on identity column not delayed", + initialInsertCount, + sessionFactory().getStatistics().getEntityInsertCount() + ); assertNull( myEntity.getId() ); s.flush(); fail( "TransactionRequiredException required upon flush" ); } - catch ( PersistenceException ex ) { + catch (PersistenceException ex) { // expected assertTyping( TransactionRequiredException.class, ex ); } @@ -103,7 +114,7 @@ public void testPersistOutsideTransactionCascadedToNonInverseCollection() { } @Test - @SuppressWarnings( {"unchecked"}) + @SuppressWarnings({ "unchecked" }) public void testPersistOutsideTransactionCascadedToInverseCollection() { long initialInsertCount = sessionFactory().getStatistics().getEntityInsertCount(); Session s = openSession(); @@ -113,12 +124,16 @@ public void testPersistOutsideTransactionCascadedToInverseCollection() { myEntity2.getInverseChildren().add( child ); child.setInverseParent( myEntity2 ); s.persist( myEntity2 ); - assertEquals( "persist on identity column not delayed", initialInsertCount, sessionFactory().getStatistics().getEntityInsertCount() ); + assertEquals( + "persist on identity column not delayed", + initialInsertCount, + sessionFactory().getStatistics().getEntityInsertCount() + ); assertNull( myEntity2.getId() ); s.flush(); fail( "TransactionRequiredException expected upon flush." ); } - catch ( PersistenceException ex ) { + catch (PersistenceException ex) { // expected assertTyping( TransactionRequiredException.class, ex ); } @@ -135,12 +150,16 @@ public void testPersistOutsideTransactionCascadedToManyToOne() { MyEntity myEntity = new MyEntity( "test-persist" ); myEntity.setSibling( new MySibling( "test-persist-sibling-out" ) ); s.persist( myEntity ); - assertEquals( "persist on identity column not delayed", initialInsertCount, sessionFactory().getStatistics().getEntityInsertCount() ); + assertEquals( + "persist on identity column not delayed", + initialInsertCount, + sessionFactory().getStatistics().getEntityInsertCount() + ); assertNull( myEntity.getId() ); s.flush(); fail( "TransactionRequiredException expected upon flush." ); } - catch ( PersistenceException ex ) { + catch (PersistenceException ex) { // expected assertTyping( TransactionRequiredException.class, ex ); } @@ -158,12 +177,16 @@ public void testPersistOutsideTransactionCascadedFromManyToOne() { MySibling sibling = new MySibling( "test-persist-sibling-in" ); sibling.setEntity( myEntity2 ); s.persist( sibling ); - assertEquals( "persist on identity column not delayed", initialInsertCount, sessionFactory().getStatistics().getEntityInsertCount() ); + assertEquals( + "persist on identity column not delayed", + initialInsertCount, + sessionFactory().getStatistics().getEntityInsertCount() + ); assertNull( myEntity2.getId() ); s.flush(); fail( "TransactionRequiredException expected upon flush." ); } - catch ( PersistenceException ex ) { + catch (PersistenceException ex) { // expected assertTyping( TransactionRequiredException.class, ex ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/hql/bitwise/BitwiseFunctionsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/hql/bitwise/BitwiseFunctionsTest.java index acfff3049c0b..1994bd2ccb95 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/hql/bitwise/BitwiseFunctionsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/hql/bitwise/BitwiseFunctionsTest.java @@ -5,6 +5,7 @@ package org.hibernate.orm.test.hql.bitwise; import org.hibernate.community.dialect.DerbyDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; @@ -21,6 +22,7 @@ public class BitwiseFunctionsTest { @Test @SkipForDialect(dialectClass = DerbyDialect.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "not support") public void test(SessionFactoryScope scope) { IntEntity five = new IntEntity(); five.setIntValue(5); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/id/CreateDeleteTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/id/CreateDeleteTest.java index b8f777bd60bf..474412a43101 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/id/CreateDeleteTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/id/CreateDeleteTest.java @@ -5,13 +5,15 @@ package org.hibernate.orm.test.id; import org.hibernate.FlushMode; +import org.hibernate.dialect.GaussDBDialect; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.Test; @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) @@ -27,6 +29,7 @@ public class CreateDeleteTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void createAndDeleteAnEntityInTheSameTransactionTest(SessionFactoryScope scope) { scope.inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/id/QuotedIdentifierTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/id/QuotedIdentifierTest.java index d9193c6ef0d1..039a3af562ee 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/id/QuotedIdentifierTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/id/QuotedIdentifierTest.java @@ -4,13 +4,7 @@ */ package org.hibernate.orm.test.id; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; - +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks.SupportsIdentityColumns; @@ -21,6 +15,13 @@ import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + import static org.junit.jupiter.api.Assertions.assertNotNull; /** @@ -37,6 +38,7 @@ public class QuotedIdentifierTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testDirectIdPropertyAccess(SessionFactoryScope scope) { QuotedIdentifier quotedIdentifier = new QuotedIdentifier(); scope.inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/identity/IdentityInsertSoleColumnTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/identity/IdentityInsertSoleColumnTest.java index bafc4c28dbe8..04e7a745f406 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/identity/IdentityInsertSoleColumnTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/identity/IdentityInsertSoleColumnTest.java @@ -4,19 +4,20 @@ */ package org.hibernate.orm.test.idgen.identity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; - +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.HANADialect; import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; -import org.junit.Test; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.orm.junit.JiraKey; +import org.junit.Test; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; import static org.junit.Assert.assertNotNull; @@ -25,7 +26,7 @@ * The purpose of this test is to insure that when an entity that contains a single column * which also happens to be an identity-generated identifier, the generated insert SQL is * correct for the dialect. - * + *

* We found through research that SAP Hana doesn't support an empty values-list clause, the * omission of the values-list clause, or any default value in the values-list clause for * the identifier column; therefore we'll skip this test for that platform. @@ -34,7 +35,7 @@ */ @JiraKey(value = "HHH-13104") @RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class) -@SkipForDialect(value=HANADialect.class, comment="SAP HANA requires at least value in insert value-list clause.") +@SkipForDialect(value = HANADialect.class, comment = "SAP HANA requires at least value in insert value-list clause.") public class IdentityInsertSoleColumnTest extends BaseEntityManagerFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { @@ -42,22 +43,27 @@ protected Class[] getAnnotatedClasses() { } @Test + @org.hibernate.testing.orm.junit.SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testEntityInsertWithSingleIdentityAttributeColumn() { // insert the entity - final Integer entityId = doInJPA( this::entityManagerFactory, entityManager -> { - final Animal animal = new Animal(); - entityManager.persist( animal ); - return animal.getId(); - } ); + final Integer entityId = doInJPA( + this::entityManagerFactory, entityManager -> { + final Animal animal = new Animal(); + entityManager.persist( animal ); + return animal.getId(); + } + ); // make sure the identifier was generated assertNotNull( entityId ); // verify the entity can be fetched - doInJPA( this::entityManagerFactory, entityManager -> { - final Animal animal = entityManager.find( Animal.class, entityId ); - assertNotNull( animal ); - } ); + doInJPA( + this::entityManagerFactory, entityManager -> { + final Animal animal = entityManager.find( Animal.class, entityId ); + assertNotNull( animal ); + } + ); } @Entity(name = "Animal") diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/identity/joinedSubClass/JoinedSubclassHierarchyWithIdentityGenerationTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/identity/joinedSubClass/JoinedSubclassHierarchyWithIdentityGenerationTest.java index d986e3c86b97..c4b49396b401 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/identity/joinedSubClass/JoinedSubclassHierarchyWithIdentityGenerationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/identity/joinedSubClass/JoinedSubclassHierarchyWithIdentityGenerationTest.java @@ -4,11 +4,14 @@ */ package org.hibernate.orm.test.idgen.identity.joinedSubClass; +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.Test; @@ -17,11 +20,12 @@ * @author Andrey Vlasov * @author Steve Ebersole */ -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsIdentityColumns.class ) -@DomainModel( annotatedClasses = Sub.class ) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@DomainModel(annotatedClasses = Sub.class) @SessionFactory public class JoinedSubclassHierarchyWithIdentityGenerationTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void shouldPersistDebtorAccountWhenParentServiceAgreementPersisted(SessionFactoryScope scope) { scope.inTransaction( (s) -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/userdefined/MixedTimingGeneratorsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/userdefined/MixedTimingGeneratorsTest.java index 8622002e5394..a6b00d1b0a08 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/userdefined/MixedTimingGeneratorsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/idgen/userdefined/MixedTimingGeneratorsTest.java @@ -14,6 +14,7 @@ import org.hibernate.annotations.SourceType; import org.hibernate.annotations.ValueGenerationType; import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.SQLServerDialect; import org.hibernate.dialect.SybaseASEDialect; @@ -50,19 +51,20 @@ /** * @author Marco Belladelli */ -@DomainModel( annotatedClasses = { +@DomainModel(annotatedClasses = { MixedTimingGeneratorsTest.AssignedEntity.class, MixedTimingGeneratorsTest.RandomEntity.class, MixedTimingGeneratorsTest.StringGeneratedEntity.class, -} ) +}) @SessionFactory -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsIdentityColumns.class ) -@Jira( "https://hibernate.atlassian.net/browse/HHH-17322" ) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@Jira("https://hibernate.atlassian.net/browse/HHH-17322") public class MixedTimingGeneratorsTest { @Test - @SkipForDialect( dialectClass = SQLServerDialect.class, reason = "SQLServer does not support setting explicit values for identity columns" ) - @SkipForDialect( dialectClass = OracleDialect.class, reason = "Oracle does not support setting explicit values for identity columns" ) - @SkipForDialect( dialectClass = SybaseASEDialect.class, reason = "Sybase does not support setting explicit values for identity columns" ) + @SkipForDialect(dialectClass = SQLServerDialect.class, reason = "SQLServer does not support setting explicit values for identity columns") + @SkipForDialect(dialectClass = OracleDialect.class, reason = "Oracle does not support setting explicit values for identity columns") + @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "Sybase does not support setting explicit values for identity columns") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testIdentityOrAssignedId(SessionFactoryScope scope) { // on execution generation scope.inTransaction( session -> session.persist( new AssignedEntity( "identity" ) ) ); @@ -79,9 +81,10 @@ public void testIdentityOrAssignedId(SessionFactoryScope scope) { } @Test - @SkipForDialect( dialectClass = SQLServerDialect.class, reason = "SQLServer does not support setting explicit values for identity columns" ) - @SkipForDialect( dialectClass = OracleDialect.class, reason = "Oracle does not support setting explicit values for identity columns" ) - @SkipForDialect( dialectClass = SybaseASEDialect.class, reason = "Sybase does not support setting explicit values for identity columns" ) + @SkipForDialect(dialectClass = SQLServerDialect.class, reason = "SQLServer does not support setting explicit values for identity columns") + @SkipForDialect(dialectClass = OracleDialect.class, reason = "Oracle does not support setting explicit values for identity columns") + @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "Sybase does not support setting explicit values for identity columns") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testIdentityOrAssignedIdStateless(SessionFactoryScope scope) { // on execution generation scope.inStatelessTransaction( session -> session.insert( new AssignedEntity( "stateless_identity" ) ) ); @@ -98,9 +101,10 @@ public void testIdentityOrAssignedIdStateless(SessionFactoryScope scope) { } @Test - @SkipForDialect( dialectClass = SQLServerDialect.class, reason = "SQLServer does not support setting explicit values for identity columns" ) - @SkipForDialect( dialectClass = OracleDialect.class, reason = "Oracle does not support setting explicit values for identity columns" ) - @SkipForDialect( dialectClass = SybaseASEDialect.class, reason = "Sybase does not support setting explicit values for identity columns" ) + @SkipForDialect(dialectClass = SQLServerDialect.class, reason = "SQLServer does not support setting explicit values for identity columns") + @SkipForDialect(dialectClass = OracleDialect.class, reason = "Oracle does not support setting explicit values for identity columns") + @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "Sybase does not support setting explicit values for identity columns") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testIdentityOrRandomId(SessionFactoryScope scope) { // on execution generation scope.inTransaction( session -> session.persist( new RandomEntity( "identity" ) ) ); @@ -164,11 +168,11 @@ public void testGeneratedPropUpdate(SessionFactoryScope scope) { } ); } - @Entity( name = "AssignedEntity" ) + @Entity(name = "AssignedEntity") public static class AssignedEntity { @Id - @GeneratedValue( generator = "identity_or_assigned" ) - @GenericGenerator( name = "identity_or_assigned", type = IdentityOrAssignedGenerator.class ) + @GeneratedValue(generator = "identity_or_assigned") + @GenericGenerator(name = "identity_or_assigned", type = IdentityOrAssignedGenerator.class) private Long id; private String name; @@ -190,11 +194,11 @@ public Long getId() { } } - @Entity( name = "RandomEntity" ) + @Entity(name = "RandomEntity") public static class RandomEntity { @Id - @GeneratedValue( generator = "identity_or_random" ) - @GenericGenerator( name = "identity_or_random", type = IdentityOrRandomGenerator.class ) + @GeneratedValue(generator = "identity_or_random") + @GenericGenerator(name = "identity_or_random", type = IdentityOrRandomGenerator.class) private Long id; private String name; @@ -215,9 +219,9 @@ public String getName() { } } - @ValueGenerationType( generatedBy = LiteralOrGeneratedStringGenerator.class ) - @Retention( RUNTIME ) - @Target( { FIELD, METHOD } ) + @ValueGenerationType(generatedBy = LiteralOrGeneratedStringGenerator.class) + @Retention(RUNTIME) + @Target({ FIELD, METHOD }) public @interface GeneratedString { /** * Specifies how the timestamp is generated. By default, it is generated @@ -227,7 +231,7 @@ public String getName() { } - @Entity( name = "StringGeneratedEntity" ) + @Entity(name = "StringGeneratedEntity") public static class StringGeneratedEntity { @Id private Long id; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/embeddable/StructAggregateEmbeddableInheritanceTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/embeddable/StructAggregateEmbeddableInheritanceTest.java index e65bc0091cd6..b5021e4532e5 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/embeddable/StructAggregateEmbeddableInheritanceTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/embeddable/StructAggregateEmbeddableInheritanceTest.java @@ -17,6 +17,7 @@ import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.PostgresPlusDialect; @@ -145,6 +146,7 @@ public void testUpdate(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.Function structfunction() does not exist.") public void testFunction(SessionFactoryScope scope) { scope.inTransaction( session -> { final ProcedureCall structFunction = session.createStoredProcedureCall( "structFunction" ) @@ -162,6 +164,7 @@ public void testFunction(SessionFactoryScope scope) { @SkipForDialect( dialectClass = PostgreSQLDialect.class, majorVersion = 10, reason = "Procedures were only introduced in version 11" ) @SkipForDialect( dialectClass = PostgresPlusDialect.class, majorVersion = 10, reason = "Procedures were only introduced in version 11" ) @SkipForDialect( dialectClass = DB2Dialect.class, reason = "DB2 does not support struct types in procedures" ) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.This statement does not declare an OUT parameter") public void testProcedure(SessionFactoryScope scope) { scope.inTransaction( session -> { final Dialect dialect = session.getJdbcServices().getDialect(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/insertordering/UpdateOrderingIdentityIdentifierTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/insertordering/UpdateOrderingIdentityIdentifierTest.java index 449331c5112c..0116a65ccbde 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/insertordering/UpdateOrderingIdentityIdentifierTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/insertordering/UpdateOrderingIdentityIdentifierTest.java @@ -6,31 +6,34 @@ import java.util.ArrayList; import java.util.List; -import jakarta.persistence.CascadeType; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.FlushModeType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; import org.hibernate.FlushMode; import org.hibernate.Session; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Parameter; import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.GaussDBDialect; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.RequiresDialectFeature; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.FlushModeType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + /** * @author Chris Cranford */ @@ -45,6 +48,7 @@ public class UpdateOrderingIdentityIdentifierTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testFailWithDelayedPostInsertIdentifier(EntityManagerFactoryScope scope) { final Long zooId = scope.fromTransaction( entityManager -> { final Zoo zoo = new Zoo(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/internal/util/ScrollableResultsObjectArrayCastingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/internal/util/ScrollableResultsObjectArrayCastingTest.java index bd4d48a6df0a..3402caaf3c87 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/internal/util/ScrollableResultsObjectArrayCastingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/internal/util/ScrollableResultsObjectArrayCastingTest.java @@ -5,28 +5,32 @@ package org.hibernate.orm.test.internal.util; import java.util.stream.Stream; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.Lob; -import jakarta.persistence.TypedQuery; -import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.RequiresDialectFeature; +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; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.TypedQuery; + /** * @author Dragoş Haiduc * @author Nathan Xu */ -@JiraKey( value = "HHH-14231" ) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsExpectedLobUsagePattern.class ) -@Jpa( annotatedClasses = ScrollableResultsObjectArrayCastingTest.Product.class ) +@JiraKey(value = "HHH-14231") +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsExpectedLobUsagePattern.class) +@Jpa(annotatedClasses = ScrollableResultsObjectArrayCastingTest.Product.class) public class ScrollableResultsObjectArrayCastingTest { @BeforeEach @@ -49,10 +53,14 @@ public void dropTestData(EntityManagerFactoryScope scope) { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNoClassCastExceptionThrown(EntityManagerFactoryScope scope) { scope.inTransaction( (entityManager) -> { - TypedQuery typedQuery = entityManager.createQuery( "select p.binaryValue from Product p", byte[].class ); + TypedQuery typedQuery = entityManager.createQuery( + "select p.binaryValue from Product p", + byte[].class + ); try (Stream stream = typedQuery.getResultStream()) { //noinspection ResultOfMethodCallIgnored stream.findFirst(); @@ -65,7 +73,8 @@ public void testNoClassCastExceptionThrown(EntityManagerFactoryScope scope) { @Entity(name = "Product") public static class Product { - @Id @GeneratedValue + @Id + @GeneratedValue Integer id; String name; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/joinedsubclassbatch/IdentityJoinedSubclassBatchingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/joinedsubclassbatch/IdentityJoinedSubclassBatchingTest.java index 16acdc3c095b..ef9c8ae52c14 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/joinedsubclassbatch/IdentityJoinedSubclassBatchingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/joinedsubclassbatch/IdentityJoinedSubclassBatchingTest.java @@ -10,15 +10,17 @@ import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.GaussDBDialect; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; import jakarta.persistence.Column; @@ -34,7 +36,6 @@ import jakarta.persistence.ManyToOne; - /** * Test batching of insert,update,delete on joined subclasses * @@ -53,6 +54,7 @@ @ServiceRegistry( settings = @Setting(name = Environment.STATEMENT_BATCH_SIZE, value = "20") ) +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class IdentityJoinedSubclassBatchingTest { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/NamedQueryTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/NamedQueryTest.java index 3f0c669dbdba..c60405012b6a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/NamedQueryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/NamedQueryTest.java @@ -9,9 +9,11 @@ import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.Setting; +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; @@ -80,6 +82,7 @@ public void testNameQueryCreationFromCriteria(EntityManagerFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.gauss's bug") public void testNativeWithMaxResults(EntityManagerFactoryScope scope) { scope.inTransaction( entityManager -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/basic/ExpressionsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/basic/ExpressionsTest.java index 8644e45a0583..821f8ef62bf7 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/basic/ExpressionsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/basic/ExpressionsTest.java @@ -14,8 +14,9 @@ import org.hibernate.Session; import org.hibernate.community.dialect.AltibaseDialect; -import org.hibernate.dialect.DB2Dialect; import org.hibernate.community.dialect.DerbyDialect; +import org.hibernate.dialect.DB2Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.PostgresPlusDialect; import org.hibernate.dialect.SybaseDialect; import org.hibernate.orm.test.jpa.metamodel.AbstractMetamodelSpecificTest; @@ -23,14 +24,14 @@ import org.hibernate.orm.test.jpa.metamodel.Product; import org.hibernate.orm.test.jpa.metamodel.Product_; import org.hibernate.query.Query; +import org.hibernate.query.common.TemporalUnit; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaDerivedRoot; import org.hibernate.query.criteria.JpaSubQuery; -import org.hibernate.query.common.TemporalUnit; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.Jira; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -101,19 +102,19 @@ public void testEmptyConjunction() { } @Test - @JiraKey( value = "HHH-15452") - public void testGetConjunctionExpressionsAndAddPredicate(){ + @JiraKey(value = "HHH-15452") + public void testGetConjunctionExpressionsAndAddPredicate() { inTransaction( entityManager -> { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); - CriteriaQuery criteria = builder.createQuery(Product.class); - Root rootClaseGrid = criteria.from(Product.class); + CriteriaQuery criteria = builder.createQuery( Product.class ); + Root rootClaseGrid = criteria.from( Product.class ); Predicate conjuncion = builder.conjunction(); - Predicate expr = builder.equal(rootClaseGrid.get("id"), "NON existing id"); + Predicate expr = builder.equal( rootClaseGrid.get( "id" ), "NON existing id" ); // Modifications to the list do not affect the query List> expressions = conjuncion.getExpressions(); - expressions.add( expr); + expressions.add( expr ); List result = entityManager.createQuery( criteria ).getResultList(); assertEquals( 1, result.size() ); @@ -265,7 +266,7 @@ public void testSumWithQuotient() { } @Test - @Jira( "https://hibernate.atlassian.net/browse/HHH-17223" ) + @Jira("https://hibernate.atlassian.net/browse/HHH-17223") public void testSumWithCoalesce() { doInJPA( this::entityManagerFactory, @@ -284,12 +285,12 @@ public void testSumWithCoalesce() { } @Test - @Jira( "https://hibernate.atlassian.net/browse/HHH-17260" ) + @Jira("https://hibernate.atlassian.net/browse/HHH-17260") public void testSumWithSubqueryPath() { doInJPA( this::entityManagerFactory, entityManager -> { - final HibernateCriteriaBuilder cb = entityManager.unwrap( Session.class ).getCriteriaBuilder(); + final HibernateCriteriaBuilder cb = entityManager.unwrap( Session.class ).getCriteriaBuilder(); final JpaCriteriaQuery criteria = cb.createQuery( Integer.class ); final JpaSubQuery subquery = criteria.subquery( Tuple.class ); final Root product = subquery.from( Product.class ); @@ -305,31 +306,38 @@ public void testSumWithSubqueryPath() { ); } - @Test @SkipForDialect(dialectClass = SybaseDialect.class, matchSubTypes = true, reason = "numeric overflows") + @Test + @SkipForDialect(dialectClass = SybaseDialect.class, matchSubTypes = true, reason = "numeric overflows") @SkipForDialect(dialectClass = PostgresPlusDialect.class, reason = "does not support extract(epoch)") @SkipForDialect(dialectClass = AltibaseDialect.class, reason = "datediff overflow limits") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.date multi overflows") public void testDateTimeOperations() { HibernateCriteriaBuilder builder = (HibernateCriteriaBuilder) this.builder; doInJPA( this::entityManagerFactory, entityManager -> { - CriteriaQuery criteria = builder.createQuery(LocalDate.class); - criteria.select( builder.addDuration( builder.localDate(), - builder.duration(2, TemporalUnit.YEAR) ) ); - entityManager.createQuery(criteria).getSingleResult(); + CriteriaQuery criteria = builder.createQuery( LocalDate.class ); + criteria.select( builder.addDuration( + builder.localDate(), + builder.duration( 2, TemporalUnit.YEAR ) + ) ); + entityManager.createQuery( criteria ).getSingleResult(); } ); doInJPA( this::entityManagerFactory, entityManager -> { - CriteriaQuery criteria = builder.createQuery(LocalDate.class); + CriteriaQuery criteria = builder.createQuery( LocalDate.class ); criteria.select( builder.addDuration( // had to call literal() here because parameter-based binding caused error from // database since it couldn't tell what sort of dateadd() function was being called - builder.literal( LocalDate.of(2000,1, 1) ), - builder.duration(2, TemporalUnit.YEAR) ) ); - assertEquals( LocalDate.of(2002,1, 1), - entityManager.createQuery(criteria).getSingleResult() ); + builder.literal( LocalDate.of( 2000, 1, 1 ) ), + builder.duration( 2, TemporalUnit.YEAR ) + ) ); + assertEquals( + LocalDate.of( 2002, 1, 1 ), + entityManager.createQuery( criteria ).getSingleResult() + ); } ); //SQL Server and others don't like this @@ -344,65 +352,81 @@ public void testDateTimeOperations() { doInJPA( this::entityManagerFactory, entityManager -> { - CriteriaQuery criteria = builder.createQuery(LocalDateTime.class); - criteria.select( builder.subtractDuration( builder.localDateTime(), Duration.ofMinutes(30) ) ); - entityManager.createQuery(criteria).getSingleResult(); + CriteriaQuery criteria = builder.createQuery( LocalDateTime.class ); + criteria.select( builder.subtractDuration( builder.localDateTime(), Duration.ofMinutes( 30 ) ) ); + entityManager.createQuery( criteria ).getSingleResult(); } ); doInJPA( this::entityManagerFactory, entityManager -> { - CriteriaQuery criteria = builder.createQuery(Duration.class); - criteria.select( builder.durationScaled( 5, builder.duration(2, TemporalUnit.HOUR ) ) ); - assertEquals( Duration.ofHours(10), entityManager.createQuery(criteria).getSingleResult() ); + CriteriaQuery criteria = builder.createQuery( Duration.class ); + criteria.select( builder.durationScaled( 5, builder.duration( 2, TemporalUnit.HOUR ) ) ); + assertEquals( Duration.ofHours( 10 ), entityManager.createQuery( criteria ).getSingleResult() ); } ); doInJPA( this::entityManagerFactory, entityManager -> { - CriteriaQuery criteria = builder.createQuery(Duration.class); - criteria.select( builder.durationSum( builder.duration(30, TemporalUnit.MINUTE ), - builder.duration(2, TemporalUnit.HOUR) ) ); - assertEquals( Duration.ofMinutes(150), entityManager.createQuery(criteria).getSingleResult() ); + CriteriaQuery criteria = builder.createQuery( Duration.class ); + criteria.select( builder.durationSum( + builder.duration( 30, TemporalUnit.MINUTE ), + builder.duration( 2, TemporalUnit.HOUR ) + ) ); + assertEquals( Duration.ofMinutes( 150 ), entityManager.createQuery( criteria ).getSingleResult() ); } ); doInJPA( this::entityManagerFactory, entityManager -> { - CriteriaQuery criteria = builder.createQuery(Long.class); - criteria.select( builder.durationByUnit( TemporalUnit.SECOND, - builder.durationSum( builder.duration(30, TemporalUnit.MINUTE), - builder.duration(2, TemporalUnit.HOUR) ) ) ); - assertEquals( 150*60L, entityManager.createQuery(criteria).getSingleResult() ); + CriteriaQuery criteria = builder.createQuery( Long.class ); + criteria.select( builder.durationByUnit( + TemporalUnit.SECOND, + builder.durationSum( + builder.duration( 30, TemporalUnit.MINUTE ), + builder.duration( 2, TemporalUnit.HOUR ) + ) + ) ); + assertEquals( 150 * 60L, entityManager.createQuery( criteria ).getSingleResult() ); } ); doInJPA( this::entityManagerFactory, entityManager -> { - CriteriaQuery criteria = builder.createQuery(Duration.class); - criteria.select( builder.durationBetween( builder.localDate(), - LocalDate.of(2000,1, 1) ) ); - entityManager.createQuery(criteria).getSingleResult(); + CriteriaQuery criteria = builder.createQuery( Duration.class ); + criteria.select( builder.durationBetween( + builder.localDate(), + LocalDate.of( 2000, 1, 1 ) + ) ); + entityManager.createQuery( criteria ).getSingleResult(); } ); doInJPA( this::entityManagerFactory, entityManager -> { - CriteriaQuery criteria = builder.createQuery(Duration.class); - criteria.select( builder.durationBetween( builder.localDate(), - builder.subtractDuration( builder.localDate(), - builder.duration(2, TemporalUnit.DAY) ) ) ); - assertEquals( Duration.ofDays(2), entityManager.createQuery(criteria).getSingleResult() ); + CriteriaQuery criteria = builder.createQuery( Duration.class ); + criteria.select( builder.durationBetween( + builder.localDate(), + builder.subtractDuration( + builder.localDate(), + builder.duration( 2, TemporalUnit.DAY ) + ) + ) ); + assertEquals( Duration.ofDays( 2 ), entityManager.createQuery( criteria ).getSingleResult() ); } ); doInJPA( this::entityManagerFactory, entityManager -> { - CriteriaQuery criteria = builder.createQuery(Duration.class); - criteria.select( builder.durationBetween( builder.localDateTime(), - builder.subtractDuration( builder.localDateTime(), - builder.duration(20, TemporalUnit.HOUR) ) ) ); - assertEquals( Duration.ofHours(20), entityManager.createQuery(criteria).getSingleResult() ); + CriteriaQuery criteria = builder.createQuery( Duration.class ); + criteria.select( builder.durationBetween( + builder.localDateTime(), + builder.subtractDuration( + builder.localDateTime(), + builder.duration( 20, TemporalUnit.HOUR ) + ) + ) ); + assertEquals( Duration.ofHours( 20 ), entityManager.createQuery( criteria ).getSingleResult() ); } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/graphs/FetchGraphTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/graphs/FetchGraphTest.java index b71fb63df1d6..23a3480274d8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/graphs/FetchGraphTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/graphs/FetchGraphTest.java @@ -6,32 +6,35 @@ import java.util.Arrays; import java.util.List; -import jakarta.persistence.CascadeType; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityGraph; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; -import jakarta.persistence.Table; import org.hibernate.Hibernate; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.graph.GraphParser; import org.hibernate.graph.GraphSemantic; -import org.hibernate.testing.orm.junit.JiraKey; + import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.RequiresDialectFeature; - +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; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.EntityGraph; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -42,7 +45,7 @@ * @author Yaroslav Prokipchyn * @author Nathan Xu */ -@JiraKey( value = "HHH-14212" ) +@JiraKey(value = "HHH-14212") @Jpa(annotatedClasses = { FetchGraphTest.LedgerRecord.class, FetchGraphTest.LedgerRecordItem.class, @@ -82,7 +85,7 @@ public void setUp(EntityManagerFactoryScope scope) { LedgerRecord ledgerRecord = new LedgerRecord(); ledgerRecord.budgetRecord = budgetRecord; ledgerRecord.trigger = trigger; - ledgerRecord.ledgerRecordItems= Arrays.asList( item1, item2 ); + ledgerRecord.ledgerRecordItems = Arrays.asList( item1, item2 ); item1.ledgerRecord = ledgerRecord; item2.ledgerRecord = ledgerRecord; @@ -106,11 +109,19 @@ public void tearDown(EntityManagerFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testCollectionEntityGraph(EntityManagerFactoryScope scope) { scope.inTransaction( entityManager -> { - final EntityGraph entityGraph = GraphParser.parse( LedgerRecord.class, "budgetRecord, ledgerRecordItems.value(financeEntity)", entityManager ); - final List records = entityManager.createQuery( "from LedgerRecord", LedgerRecord.class ) + final EntityGraph entityGraph = GraphParser.parse( + LedgerRecord.class, + "budgetRecord, ledgerRecordItems.value(financeEntity)", + entityManager + ); + final List records = entityManager.createQuery( + "from LedgerRecord", + LedgerRecord.class + ) .setHint( GraphSemantic.FETCH.getJpaHintName(), entityGraph ) .getResultList(); assertThat( records.size(), is( 1 ) ); @@ -118,7 +129,7 @@ public void testCollectionEntityGraph(EntityManagerFactoryScope scope) { assertFalse( Hibernate.isInitialized( record.trigger ) ); assertTrue( Hibernate.isInitialized( record.budgetRecord ) ); assertFalse( Hibernate.isInitialized( record.budgetRecord.trigger ) ); - assertTrue( Hibernate.isInitialized( record.ledgerRecordItems) ); + assertTrue( Hibernate.isInitialized( record.ledgerRecordItems ) ); assertThat( record.ledgerRecordItems.size(), is( 2 ) ); record.ledgerRecordItems.forEach( item -> { assertSame( record, item.ledgerRecord ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockTest.java index 3710d83115e3..a366786923ae 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockTest.java @@ -22,6 +22,7 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.community.dialect.AltibaseDialect; import org.hibernate.community.dialect.FirebirdDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.CockroachDialect; import org.hibernate.community.dialect.DerbyDialect; @@ -1186,6 +1187,7 @@ public void testLockTimeoutEMProps() throws Exception { @SkipForDialect(value = CockroachDialect.class, comment = "Cockroach supports the 'for no key update' syntax but it doesn't work") @SkipForDialect(value = FirebirdDialect.class, comment = "Seems like FK constraint checks are not compatible with exclusive locks") @SkipForDialect(value = AltibaseDialect.class, comment = "Seems like FK constraint checks are not compatible with exclusive locks") + @SkipForDialect(value = GaussDBDialect.class, comment = "Seems like FK constraint checks are not compatible with exclusive locks") public void testLockInsertFkTarget() { Lock lock = new Lock(); lock.setName( "name" ); @@ -1225,6 +1227,7 @@ public void testLockInsertFkTarget() { @SkipForDialect(value = CockroachDialect.class, comment = "Cockroach supports the 'for no key update' syntax but it doesn't work") @SkipForDialect(value = FirebirdDialect.class, comment = "Seems like FK constraint checks are not compatible with exclusive locks") @SkipForDialect(value = AltibaseDialect.class, comment = "FK constraint checks are not compatible with exclusive locks") + @SkipForDialect(value = GaussDBDialect.class, comment = "FK constraint checks are not compatible with exclusive locks") public void testLockUpdateFkTarget() { Lock lock1 = new Lock(); lock1.setName( "l1" ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/naturalid/MutableNaturalIdTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/naturalid/MutableNaturalIdTest.java index 4862c0032817..08ad9fc4943a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/naturalid/MutableNaturalIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/naturalid/MutableNaturalIdTest.java @@ -5,13 +5,13 @@ package org.hibernate.orm.test.jpa.naturalid; import org.hibernate.community.dialect.AltibaseDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.OracleDialect; +import org.hibernate.orm.test.jpa.model.AbstractJPATest; import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.SkipForDialect; -import org.hibernate.orm.test.jpa.model.AbstractJPATest; - import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -62,6 +62,7 @@ public void testSimpleNaturalIdLoadAccessCacheWithUpdate() { @Test @JiraKey(value = "HHH-7304") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testInLineSynchWithIdentityColumn() { inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerOneToManyOrphanWithIdentityIdTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerOneToManyOrphanWithIdentityIdTest.java index 0fc453912e74..a50e94a5fba4 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerOneToManyOrphanWithIdentityIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerOneToManyOrphanWithIdentityIdTest.java @@ -8,12 +8,14 @@ import java.util.List; import org.hibernate.Hibernate; +import org.hibernate.dialect.GaussDBDialect; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -38,6 +40,7 @@ ) @JiraKey(value = "HHH-15258") @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class EagerOneToManyOrphanWithIdentityIdTest { @AfterEach diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/LazyOneToManyOrphanWithIdentityIdTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/LazyOneToManyOrphanWithIdentityIdTest.java index afc300dbf8b2..1ca9059d1c9b 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/LazyOneToManyOrphanWithIdentityIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/LazyOneToManyOrphanWithIdentityIdTest.java @@ -8,12 +8,14 @@ import java.util.List; import org.hibernate.Hibernate; +import org.hibernate.dialect.GaussDBDialect; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -37,6 +39,7 @@ ) @JiraKey(value = "HHH-15258") @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class LazyOneToManyOrphanWithIdentityIdTest { @AfterEach diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/PersistAndQueryingInSameTransactionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/PersistAndQueryingInSameTransactionTest.java index aeb82a6ff57a..5a3eda3a4ce8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/PersistAndQueryingInSameTransactionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/PersistAndQueryingInSameTransactionTest.java @@ -9,14 +9,16 @@ import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; -import org.hibernate.testing.util.uuid.SafeRandomUUIDGenerator; +import org.hibernate.dialect.GaussDBDialect; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.RequiresDialectFeature; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.testing.orm.junit.SkipForDialect; +import org.hibernate.testing.util.uuid.SafeRandomUUIDGenerator; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -42,6 +44,7 @@ @SessionFactory @JiraKey(value = "HHH-15512") @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class PersistAndQueryingInSameTransactionTest { @AfterEach diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NativeQueryResultTypeAutoDiscoveryTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NativeQueryResultTypeAutoDiscoveryTest.java index 40a22d98f1c8..08f94d6d7061 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NativeQueryResultTypeAutoDiscoveryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NativeQueryResultTypeAutoDiscoveryTest.java @@ -24,6 +24,7 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.community.dialect.AltibaseDialect; import org.hibernate.community.dialect.FirebirdDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.AbstractTransactSQLDialect; import org.hibernate.dialect.CockroachDialect; @@ -155,6 +156,7 @@ public void bitType() { @SkipForDialect(dialectClass = OracleDialect.class, reason = "Oracle maps tinyint to number") @SkipForDialect(dialectClass = FirebirdDialect.class, reason = "No support for the tinyint datatype so we use smallint") @SkipForDialect(dialectClass = AltibaseDialect.class, reason = "Altibase maps tinyint to smallint") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.Turns tinyints into shorts in result sets and advertises the type as short in the metadata") public void tinyintType() { createEntityManagerFactory( TinyintEntity.class ); doTest( TinyintEntity.class, (byte)127 ); @@ -297,6 +299,7 @@ public void lobTypes() { @SkipForDialect(dialectClass = PostgresPlusDialect.class, reason = "EDB maps DATE and TIME to TIMESTAMP") @SkipForDialect(dialectClass = SybaseDialect.class, reason = "Sybase maps DATE and TIME to TIMESTAMP", matchSubTypes = true) @SkipForDialect(dialectClass = AltibaseDialect.class, reason = "Altibase maps DATE and TIME to TIMESTAMP") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.Gaussdb's Oracle model maps DATE and TIME to TIMESTAMP") public void dateTimeTypes() { createEntityManagerFactory( DateEntity.class, diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NativeQueryWithDatetimesTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NativeQueryWithDatetimesTest.java index b601baf28285..939c699f5434 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NativeQueryWithDatetimesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/NativeQueryWithDatetimesTest.java @@ -8,6 +8,7 @@ import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.PostgresPlusDialect; @@ -26,6 +27,7 @@ public class NativeQueryWithDatetimesTest { @SkipForDialect(dialectClass = PostgresPlusDialect.class) @SkipForDialect(dialectClass = OracleDialect.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.gauss will map localdate to timestamp") @Test void test(EntityManagerFactoryScope scope) { scope.inTransaction(s -> s.persist(new Datetimes())); Object[] result = scope.fromTransaction(s -> (Object[]) s.createNativeQuery("select ctime, cdate, cdatetime from tdatetimes", Object[].class).getSingleResult()); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/QueryTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/QueryTest.java index e601476775b5..17e0ee5b030a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/QueryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/query/QueryTest.java @@ -28,6 +28,7 @@ import org.hibernate.dialect.CockroachDialect; import org.hibernate.dialect.DB2Dialect; import org.hibernate.community.dialect.DerbyDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.PostgresPlusDialect; @@ -381,6 +382,7 @@ public Class getParameterType() { @Test @SkipForDialect(value = PostgreSQLDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") + @SkipForDialect(value = GaussDBDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") @SkipForDialect(value = PostgresPlusDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") @SkipForDialect(value = CockroachDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") public void testNativeQueryNullPositionalParameter() throws Exception { @@ -416,6 +418,7 @@ public void testNativeQueryNullPositionalParameter() throws Exception { @Test @JiraKey(value = "HHH-10161") @SkipForDialect(value = PostgreSQLDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") + @SkipForDialect(value = GaussDBDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") @SkipForDialect(value = PostgresPlusDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") @SkipForDialect(value = CockroachDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") public void testNativeQueryNullPositionalParameterParameter() throws Exception { @@ -467,6 +470,7 @@ public Class getParameterType() { @Test @SkipForDialect(value = PostgreSQLDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") + @SkipForDialect(value = GaussDBDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") @SkipForDialect(value = PostgresPlusDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") @SkipForDialect(value = CockroachDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") public void testNativeQueryNullNamedParameter() throws Exception { @@ -502,6 +506,7 @@ public void testNativeQueryNullNamedParameter() throws Exception { @Test @JiraKey(value = "HHH-10161") @SkipForDialect(value = PostgreSQLDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") + @SkipForDialect(value = GaussDBDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") @SkipForDialect(value = PostgresPlusDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") @SkipForDialect(value = CockroachDialect.class, jiraKey = "HHH-10312", comment = "Cannot determine the parameter types and bind type is unknown because the value is null") public void testNativeQueryNullNamedParameterParameter() throws Exception { @@ -574,6 +579,7 @@ public void testQueryContainsQuotedSemicolonWithLimit() { @Test @JiraKey("HHH-18033") + @SkipForDialect(value = GaussDBDialect.class, comment = "Doesn't support semicolon as ending of statement") public void testNativeQueryContainsQuotedSemicolonWithLimit() { EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); @@ -600,6 +606,7 @@ public void testNativeQueryContainsQuotedSemicolonWithLimit() { @SkipForDialect(value = SybaseDialect.class, comment = "Doesn't support semicolon as ending of statement") @SkipForDialect(value = DerbyDialect.class, comment = "Doesn't support semicolon as ending of statement") @SkipForDialect(value = DB2Dialect.class, comment = "Doesn't support semicolon as ending of statement") + @SkipForDialect(value = GaussDBDialect.class, comment = "Doesn't support semicolon as ending of statement") public void testNativeQueryContainsQuotedSemicolonAndEndsWithSemicolonWithLimit() { EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/SchemaDatabaseFileGenerationFailureTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/SchemaDatabaseFileGenerationFailureTest.java index 056673d79be7..7d6162254dd8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/SchemaDatabaseFileGenerationFailureTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/SchemaDatabaseFileGenerationFailureTest.java @@ -19,6 +19,7 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.jpa.boot.spi.Bootstrap; import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder; @@ -74,6 +75,7 @@ public void destroy() { @JiraKey(value = "HHH-12192") @SkipForDialect(dialectClass = PostgreSQLDialect.class, matchSubTypes = true, reason = "on postgres we send 'set client_min_messages = WARNING'") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.on gauss we send 'set client_min_messages = WARNING'") public void testErrorMessageContainsTheFailingDDLCommand() { try { entityManagerFactoryBuilder.generateSchema(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/SchemaScriptFileGenerationFailureTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/SchemaScriptFileGenerationFailureTest.java index 6e8f8ad4461d..517176df1004 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/SchemaScriptFileGenerationFailureTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/schemagen/SchemaScriptFileGenerationFailureTest.java @@ -17,6 +17,7 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.jpa.boot.spi.Bootstrap; import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder; @@ -65,6 +66,7 @@ public void destroy() { @JiraKey(value = "HHH-12192") @SkipForDialect(dialectClass = PostgreSQLDialect.class, matchSubTypes = true, reason = "on postgres we send 'set client_min_messages = WARNING'") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.on gauss we send 'set client_min_messages = WARNING'") public void testErrorMessageContainsTheFailingDDLCommand() { try { entityManagerFactoryBuilder.generateSchema(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/transaction/batch/JtaWithStatementsBatchTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/transaction/batch/JtaWithStatementsBatchTest.java index db5665601cc5..42edf23c3162 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/transaction/batch/JtaWithStatementsBatchTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/transaction/batch/JtaWithStatementsBatchTest.java @@ -6,16 +6,18 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.BatchSettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.orm.test.jpa.transaction.JtaPlatformSettingProvider; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.jta.TestingJtaPlatformImpl; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.RequiresDialectFeature; import org.hibernate.testing.orm.junit.Setting; import org.hibernate.testing.orm.junit.SettingProvider; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; import jakarta.persistence.FlushModeType; @@ -61,6 +63,7 @@ public class JtaWithStatementsBatchTest extends AbstractJtaBatchTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testUnableToReleaseStatementMessageIsNotLogged(EntityManagerFactoryScope scope) { TransactionManager transactionManager = TestingJtaPlatformImpl.INSTANCE.getTransactionManager(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/lob/LobStringFunctionsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/lob/LobStringFunctionsTest.java index a9f290bdc3d7..507acaa04179 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/lob/LobStringFunctionsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/lob/LobStringFunctionsTest.java @@ -7,12 +7,14 @@ import java.sql.Clob; import java.util.List; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.DomainModel; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -67,6 +69,7 @@ public void tearDown(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class) public void testLengthFunction(SessionFactoryScope scope) { scope.inTransaction( session -> { final Query query = session.createQuery( @@ -86,6 +89,7 @@ public void testLengthFunction(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class) public void testOctetLengthFunction(SessionFactoryScope scope) { scope.inTransaction( session -> { final Query query = session.createQuery( @@ -106,6 +110,7 @@ public void testOctetLengthFunction(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class) public void testBitLengthFunction(SessionFactoryScope scope) { scope.inTransaction( session -> { final Query query = session.createQuery( @@ -126,6 +131,7 @@ public void testBitLengthFunction(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class) public void testConcatFunction(SessionFactoryScope scope) { scope.inTransaction( session -> { // Use trim('') instead of '' since Sybase interprets that as single space string... diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/lob/LongByteArrayTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/lob/LongByteArrayTest.java index 3c5b445a43d5..237077c7598f 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/lob/LongByteArrayTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/lob/LongByteArrayTest.java @@ -6,6 +6,7 @@ import java.util.Arrays; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.SybaseASEDialect; import org.hibernate.testing.orm.junit.SessionFactory; @@ -29,6 +30,7 @@ public abstract class LongByteArrayTest { private static final int ARRAY_SIZE = 10000; @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testBoundedLongByteArrayAccess(SessionFactoryScope scope) { byte[] original = buildRecursively( ARRAY_SIZE, true ); byte[] changed = buildRecursively( ARRAY_SIZE, false ); @@ -79,6 +81,7 @@ public void testBoundedLongByteArrayAccess(SessionFactoryScope scope) { @Test @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "Sybase returns byte[]{0}") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testEmptyArray(SessionFactoryScope scope) { byte[] empty = new byte[] {}; @@ -102,6 +105,7 @@ public void testEmptyArray(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testSaving(SessionFactoryScope scope) { byte[] value = buildRecursively( ARRAY_SIZE, true ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/locking/paging/PagingAndLockingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/locking/paging/PagingAndLockingTest.java index 347bd781e62a..997e66713a13 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/locking/paging/PagingAndLockingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/locking/paging/PagingAndLockingTest.java @@ -10,11 +10,13 @@ import jakarta.persistence.criteria.CriteriaQuery; import org.hibernate.LockMode; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.NativeQuery; import org.hibernate.query.Query; import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -71,6 +73,7 @@ public void testHql() { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.gauss's bug") public void testCriteria() { inTransaction( s -> { @@ -96,6 +99,7 @@ public void testCriteria() { @Test // @Ignore( "Support for locking on native-sql queries not yet implemented" ) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.not support") public void testNativeSql() { inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/array/ArrayOfArraysTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/array/ArrayOfArraysTest.java index 988b2e50b3aa..9f9850f1c77f 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/array/ArrayOfArraysTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/array/ArrayOfArraysTest.java @@ -9,6 +9,7 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.CockroachDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.SkipForDialect; import org.hibernate.type.SqlTypes; @@ -39,6 +40,7 @@ public class ArrayOfArraysTest { @ServiceRegistry( settings = @Setting( name = AvailableSettings.HBM2DDL_AUTO, value = "create-drop" ) ) @Test @SkipForDialect( dialectClass = CockroachDialect.class, reason = "Unable to find server array type for provided name bytes" ) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.Method com.huawei.gaussdb.jdbc.jdbc.PgArray.getArrayImpl(long,int,Map) is not yet implemented.") public void testDoubleByteArrayWorks(SessionFactoryScope scope) { final Long id = scope.fromTransaction( session -> { final EntityWithDoubleByteArray entity = new EntityWithDoubleByteArray(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/BlobByteArrayTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/BlobByteArrayTest.java index d057f7b7b7a8..0e5eee36bc11 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/BlobByteArrayTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/BlobByteArrayTest.java @@ -4,14 +4,16 @@ */ package org.hibernate.orm.test.mapping.basic; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Lob; - +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.Test; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; + import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; import static org.junit.Assert.assertArrayEquals; @@ -23,26 +25,31 @@ public class BlobByteArrayTest extends BaseEntityManagerFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { return new Class[] { - Product.class + Product.class }; } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void test() { - Integer productId = doInJPA(this::entityManagerFactory, entityManager -> { - final Product product = new Product(); - product.setId(1); - product.setName("Mobile phone"); - product.setImage(new byte[] {1, 2, 3}); - - entityManager.persist(product); - return product.getId(); - }); - doInJPA(this::entityManagerFactory, entityManager -> { - Product product = entityManager.find(Product.class, productId); - - assertArrayEquals(new byte[] {1, 2, 3}, product.getImage()); - }); + Integer productId = doInJPA( + this::entityManagerFactory, entityManager -> { + final Product product = new Product(); + product.setId( 1 ); + product.setName( "Mobile phone" ); + product.setImage( new byte[] { 1, 2, 3 } ); + + entityManager.persist( product ); + return product.getId(); + } + ); + doInJPA( + this::entityManagerFactory, entityManager -> { + Product product = entityManager.find( Product.class, productId ); + + assertArrayEquals( new byte[] { 1, 2, 3 }, product.getImage() ); + } + ); } //tag::basic-blob-byte-array-example[] @@ -59,7 +66,7 @@ public static class Product { //Getters and setters are omitted for brevity - //end::basic-blob-byte-array-example[] + //end::basic-blob-byte-array-example[] public Integer getId() { return id; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/ByteArrayMappingTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/ByteArrayMappingTests.java index 7f6a7f1fdbbc..edb61817bc49 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/ByteArrayMappingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/ByteArrayMappingTests.java @@ -5,14 +5,11 @@ package org.hibernate.orm.test.mapping.basic; import java.sql.Types; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Lob; -import jakarta.persistence.Table; import org.hibernate.annotations.JavaType; import org.hibernate.cfg.AvailableSettings; import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping; import org.hibernate.metamodel.spi.MappingMetamodelImplementor; @@ -27,9 +24,15 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.Table; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; @@ -47,25 +50,28 @@ public class ByteArrayMappingTests { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void verifyMappings(SessionFactoryScope scope) { final MappingMetamodelImplementor mappingMetamodel = scope.getSessionFactory() .getRuntimeMetamodels() .getMappingMetamodel(); final Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect(); final JdbcTypeRegistry jdbcTypeRegistry = mappingMetamodel.getTypeConfiguration().getJdbcTypeRegistry(); - final EntityPersister entityDescriptor = mappingMetamodel.getEntityDescriptor(EntityOfByteArrays.class); + final EntityPersister entityDescriptor = mappingMetamodel.getEntityDescriptor( EntityOfByteArrays.class ); { - final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("primitive"); + final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "primitive" ); final JdbcMapping jdbcMapping = primitive.getJdbcMapping(); - assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(byte[].class)); + assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( byte[].class ) ); assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.VARBINARY ) ) ); } { - final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("wrapper"); + final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "wrapper" ); final JdbcMapping jdbcMapping = primitive.getJdbcMapping(); - assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(Byte[].class)); + assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( Byte[].class ) ); if ( dialect.supportsStandardArrays() ) { assertThat( jdbcMapping.getJdbcType(), instanceOf( ArrayJdbcType.class ) ); assertThat( @@ -76,49 +82,58 @@ public void verifyMappings(SessionFactoryScope scope) { else { assertThat( jdbcMapping.getJdbcType().getDdlTypeCode(), - isOneOf( SqlTypes.ARRAY, SqlTypes.JSON, SqlTypes.SQLXML, SqlTypes.VARBINARY, SqlTypes.LONG32VARCHAR ) + isOneOf( + SqlTypes.ARRAY, + SqlTypes.JSON, + SqlTypes.SQLXML, + SqlTypes.VARBINARY, + SqlTypes.LONG32VARCHAR + ) ); } } { - final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("wrapperOld"); + final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "wrapperOld" ); final JdbcMapping jdbcMapping = primitive.getJdbcMapping(); - assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(Byte[].class)); + assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( Byte[].class ) ); assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.VARBINARY ) ) ); } { - final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("primitiveLob"); + final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "primitiveLob" ); final JdbcMapping jdbcMapping = primitive.getJdbcMapping(); - assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(byte[].class)); + assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( byte[].class ) ); assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.BLOB ) ) ); } { - final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("wrapperLob"); + final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "wrapperLob" ); final JdbcMapping jdbcMapping = primitive.getJdbcMapping(); - assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(Byte[].class)); + assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( Byte[].class ) ); assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.BLOB ) ) ); } scope.inTransaction( (session) -> { session.persist( - new EntityOfByteArrays(1, "abc".getBytes(), new Byte[] { (byte) 1 }) + new EntityOfByteArrays( 1, "abc".getBytes(), new Byte[] { (byte) 1 } ) ); } ); scope.inTransaction( - (session) -> session.get(EntityOfByteArrays.class, 1) + (session) -> session.get( EntityOfByteArrays.class, 1 ) ); } @AfterEach public void dropTestData(SessionFactoryScope scope) { scope.inTransaction( - (session) -> session.createMutationQuery("delete EntityOfByteArrays").executeUpdate() + (session) -> session.createMutationQuery( "delete EntityOfByteArrays" ).executeUpdate() ); } @@ -133,7 +148,7 @@ public static class EntityOfByteArrays { // mapped as VARBINARY private byte[] primitive; private Byte[] wrapper; - @JavaType( ByteArrayJavaType.class ) + @JavaType(ByteArrayJavaType.class) private Byte[] wrapperOld; // mapped as (materialized) BLOB @@ -154,7 +169,12 @@ public EntityOfByteArrays(Integer id, byte[] primitive, Byte[] wrapper) { this.wrapperLob = wrapper; } - public EntityOfByteArrays(Integer id, byte[] primitive, Byte[] wrapper, byte[] primitiveLob, Byte[] wrapperLob) { + public EntityOfByteArrays( + Integer id, + byte[] primitive, + Byte[] wrapper, + byte[] primitiveLob, + Byte[] wrapperLob) { this.id = id; this.primitive = primitive; this.wrapper = wrapper; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/WrapperArrayHandlingLegacyTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/WrapperArrayHandlingLegacyTests.java index cb37bc6228dc..77df58b3e84f 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/WrapperArrayHandlingLegacyTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/WrapperArrayHandlingLegacyTests.java @@ -9,6 +9,7 @@ import org.hibernate.annotations.Nationalized; import org.hibernate.cfg.AvailableSettings; import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.NationalizationSupport; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping; @@ -21,6 +22,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -47,51 +49,56 @@ public class WrapperArrayHandlingLegacyTests { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void verifyByteArrayMappings(SessionFactoryScope scope) { final MappingMetamodelImplementor mappingMetamodel = scope.getSessionFactory() .getRuntimeMetamodels() .getMappingMetamodel(); final JdbcTypeRegistry jdbcTypeRegistry = mappingMetamodel.getTypeConfiguration().getJdbcTypeRegistry(); - final EntityPersister entityDescriptor = mappingMetamodel.getEntityDescriptor( WrapperArrayHandlingLegacyTests.EntityOfByteArrays.class); + final EntityPersister entityDescriptor = mappingMetamodel.getEntityDescriptor( WrapperArrayHandlingLegacyTests.EntityOfByteArrays.class ); { - final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("primitive"); + final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "primitive" ); final JdbcMapping jdbcMapping = primitive.getJdbcMapping(); - assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(byte[].class)); + assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( byte[].class ) ); assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.VARBINARY ) ) ); } { - final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("wrapper"); + final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "wrapper" ); final JdbcMapping jdbcMapping = primitive.getJdbcMapping(); - assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(Byte[].class)); + assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( Byte[].class ) ); assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.VARBINARY ) ) ); } { - final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("primitiveLob"); + final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "primitiveLob" ); final JdbcMapping jdbcMapping = primitive.getJdbcMapping(); - assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(byte[].class)); + assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( byte[].class ) ); assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.BLOB ) ) ); } { - final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("wrapperLob"); + final BasicAttributeMapping primitive = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "wrapperLob" ); final JdbcMapping jdbcMapping = primitive.getJdbcMapping(); - assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(Byte[].class)); + assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( Byte[].class ) ); assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcTypeRegistry.getDescriptor( Types.BLOB ) ) ); } scope.inTransaction( (session) -> { session.persist( - new EntityOfByteArrays( 1, "abc".getBytes(), new Byte[] { (byte) 1 }) + new EntityOfByteArrays( 1, "abc".getBytes(), new Byte[] { (byte) 1 } ) ); } ); scope.inTransaction( - (session) -> session.get( EntityOfByteArrays.class, 1) + (session) -> session.get( EntityOfByteArrays.class, 1 ) ); } @@ -101,31 +108,35 @@ public void verifyCharacterArrayMappings(SessionFactoryScope scope) { .getRuntimeMetamodels() .getMappingMetamodel(); final JdbcTypeRegistry jdbcRegistry = mappingMetamodel.getTypeConfiguration().getJdbcTypeRegistry(); - final EntityPersister entityDescriptor = mappingMetamodel.getEntityDescriptor( WrapperArrayHandlingLegacyTests.EntityWithCharArrays.class); + final EntityPersister entityDescriptor = mappingMetamodel.getEntityDescriptor( WrapperArrayHandlingLegacyTests.EntityWithCharArrays.class ); { - final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("primitive"); + final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "primitive" ); final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping(); - assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcRegistry.getDescriptor( Types.VARCHAR))); + assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcRegistry.getDescriptor( Types.VARCHAR ) ) ); } { - final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("wrapper"); + final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "wrapper" ); final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping(); - assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcRegistry.getDescriptor( Types.VARCHAR))); + assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcRegistry.getDescriptor( Types.VARCHAR ) ) ); } { - final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("primitiveClob"); + final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "primitiveClob" ); final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping(); - assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcRegistry.getDescriptor( Types.CLOB))); + assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcRegistry.getDescriptor( Types.CLOB ) ) ); } { - final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("wrapperClob"); + final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "wrapperClob" ); final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping(); - assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcRegistry.getDescriptor( Types.CLOB))); + assertThat( jdbcMapping.getJdbcType(), equalTo( jdbcRegistry.getDescriptor( Types.CLOB ) ) ); } } @@ -135,35 +146,51 @@ public void verifyCharacterArrayNationalizedMappings(SessionFactoryScope scope) .getRuntimeMetamodels() .getMappingMetamodel(); final EntityPersister entityDescriptor = mappingMetamodel.getEntityDescriptor( - WrapperArrayHandlingLegacyTests.EntityWithCharArrays.class); + WrapperArrayHandlingLegacyTests.EntityWithCharArrays.class ); final JdbcTypeRegistry jdbcTypeRegistry = mappingMetamodel.getTypeConfiguration().getJdbcTypeRegistry(); final Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect(); final NationalizationSupport nationalizationSupport = dialect.getNationalizationSupport(); { - final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("primitiveNVarchar"); + final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "primitiveNVarchar" ); final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping(); - assertThat( jdbcMapping.getJdbcType(), is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getVarcharVariantCode()))); + assertThat( + jdbcMapping.getJdbcType(), + is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getVarcharVariantCode() ) ) + ); } { - final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("wrapperNVarchar"); + final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "wrapperNVarchar" ); final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping(); - assertThat( jdbcMapping.getJdbcType(), is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getVarcharVariantCode()))); + assertThat( + jdbcMapping.getJdbcType(), + is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getVarcharVariantCode() ) ) + ); } { - final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("primitiveNClob"); + final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "primitiveNClob" ); final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping(); - assertThat( jdbcMapping.getJdbcType(), is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getClobVariantCode()))); + assertThat( + jdbcMapping.getJdbcType(), + is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getClobVariantCode() ) ) + ); } { - final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("wrapperNClob"); + final BasicAttributeMapping attributeMapping = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( + "wrapperNClob" ); final JdbcMapping jdbcMapping = attributeMapping.getJdbcMapping(); - assertThat( jdbcMapping.getJdbcType(), is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getClobVariantCode()))); + assertThat( + jdbcMapping.getJdbcType(), + is( jdbcTypeRegistry.getDescriptor( nationalizationSupport.getClobVariantCode() ) ) + ); } } @@ -172,8 +199,8 @@ public void verifyCharacterArrayNationalizedMappings(SessionFactoryScope scope) public void dropTestData(SessionFactoryScope scope) { scope.inTransaction( (session) -> { - session.createMutationQuery("delete EntityOfByteArrays").executeUpdate(); - session.createMutationQuery("delete EntityWithCharArrays").executeUpdate(); + session.createMutationQuery( "delete EntityOfByteArrays" ).executeUpdate(); + session.createMutationQuery( "delete EntityWithCharArrays" ).executeUpdate(); } ); } @@ -207,7 +234,12 @@ public EntityOfByteArrays(Integer id, byte[] primitive, Byte[] wrapper) { this.wrapperLob = wrapper; } - public EntityOfByteArrays(Integer id, byte[] primitive, Byte[] wrapper, byte[] primitiveLob, Byte[] wrapperLob) { + public EntityOfByteArrays( + Integer id, + byte[] primitive, + Byte[] wrapper, + byte[] primitiveLob, + Byte[] wrapperLob) { this.id = id; this.primitive = primitive; this.wrapper = wrapper; @@ -215,6 +247,7 @@ public EntityOfByteArrays(Integer id, byte[] primitive, Byte[] wrapper, byte[] p this.wrapperLob = wrapperLob; } } + @Entity(name = "EntityWithCharArrays") @Table(name = "EntityWithCharArrays") public static class EntityWithCharArrays { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/XmlMappingTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/XmlMappingTests.java index 077af442343e..4326eb845650 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/XmlMappingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/XmlMappingTests.java @@ -10,8 +10,9 @@ import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.cfg.AvailableSettings; import org.hibernate.community.dialect.AltibaseDialect; -import org.hibernate.dialect.HANADialect; import org.hibernate.community.dialect.DerbyDialect; +import org.hibernate.dialect.GaussDBDialect; +import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.dialect.SybaseDialect; import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping; @@ -99,6 +100,7 @@ public void tearDown(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void verifyMappings(SessionFactoryScope scope) { final MappingMetamodelImplementor mappingMetamodel = scope.getSessionFactory() .getRuntimeMetamodels() @@ -123,6 +125,7 @@ public void verifyMappings(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void verifyReadWorks(SessionFactoryScope scope) { scope.inTransaction( (session) -> { @@ -140,9 +143,10 @@ public void verifyReadWorks(SessionFactoryScope scope) { @SkipForDialect(dialectClass = SybaseDialect.class, matchSubTypes = true, reason = "Sybase doesn't support comparing LOBs with the = operator") @SkipForDialect(dialectClass = OracleDialect.class, matchSubTypes = true, reason = "Oracle doesn't support comparing JSON with the = operator") @SkipForDialect(dialectClass = AltibaseDialect.class, reason = "Altibase doesn't support comparing CLOBs with the = operator") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void verifyComparisonWorks(SessionFactoryScope scope) { scope.inTransaction( - (session) -> { + (session) -> { EntityWithXml entityWithJson = session.createQuery( "from EntityWithXml e where e.stringMap = :param", EntityWithXml.class @@ -164,14 +168,14 @@ public static class EntityWithXml { private Integer id; //tag::basic-xml-example[] - @JdbcTypeCode( SqlTypes.SQLXML ) + @JdbcTypeCode(SqlTypes.SQLXML) private Map stringMap; //end::basic-xml-example[] - @JdbcTypeCode( SqlTypes.SQLXML ) + @JdbcTypeCode(SqlTypes.SQLXML) private Map objectMap; - @JdbcTypeCode( SqlTypes.SQLXML ) + @JdbcTypeCode(SqlTypes.SQLXML) private List list; public EntityWithXml() { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/AggregateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/AggregateTest.java index 42cdd99b92c2..22398ef2367f 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/AggregateTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/AggregateTest.java @@ -4,20 +4,22 @@ */ package org.hibernate.orm.test.mapping.embeddable; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.dialect.GaussDBDialect; +import org.hibernate.type.SqlTypes; + import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.JiraKey; - import org.hibernate.testing.orm.junit.RequiresDialectFeature; -import org.hibernate.type.SqlTypes; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonAggregate.class) @@ -52,30 +54,40 @@ protected void cleanupTest() { @Test @JiraKey("HHH-17294") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testDirtyCheckingJsonAggregate() { sessionFactoryScope().inTransaction( entityManager -> { JsonHolder aggregateHolder = entityManager.find( JsonHolder.class, 1L ); - Assertions.assertEquals("String 'abc'", aggregateHolder.getAggregate().getTheString()); + Assertions.assertEquals( "String 'abc'", aggregateHolder.getAggregate().getTheString() ); aggregateHolder.getAggregate().setTheString( "MyString" ); entityManager.flush(); entityManager.clear(); - Assertions.assertEquals( "MyString", entityManager.find( JsonHolder.class, 1L ).getAggregate().getTheString() ); + Assertions.assertEquals( + "MyString", entityManager.find( JsonHolder.class, 1L ) + .getAggregate() + .getTheString() + ); } ); } @Test @JiraKey("HHH-17294") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testDirtyCheckingXmlAggregate() { sessionFactoryScope().inTransaction( entityManager -> { XmlHolder aggregateHolder = entityManager.find( XmlHolder.class, 1L ); - Assertions.assertEquals("String 'abc'", aggregateHolder.getAggregate().getTheString()); + Assertions.assertEquals( "String 'abc'", aggregateHolder.getAggregate().getTheString() ); aggregateHolder.getAggregate().setTheString( "MyString" ); entityManager.flush(); entityManager.clear(); - Assertions.assertEquals( "MyString", entityManager.find( XmlHolder.class, 1L ).getAggregate().getTheString() ); + Assertions.assertEquals( + "MyString", entityManager.find( XmlHolder.class, 1L ) + .getAggregate() + .getTheString() + ); } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/JsonEmbeddableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/JsonEmbeddableTest.java index 7544a33c1332..a70ae34630c8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/JsonEmbeddableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/JsonEmbeddableTest.java @@ -19,6 +19,8 @@ import java.util.UUID; import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.dialect.GaussDBDialect; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.hibernate.type.SqlTypes; import org.hibernate.testing.orm.domain.gambit.EntityOfBasics; @@ -219,6 +221,7 @@ public void testUpdateAggregate() { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonComponentUpdate.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.do not support") public void testUpdateAggregateMember() { sessionFactoryScope().inTransaction( entityManager -> { @@ -232,6 +235,7 @@ public void testUpdateAggregateMember() { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonComponentUpdate.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.do not support") public void testUpdateMultipleAggregateMembers() { sessionFactoryScope().inTransaction( entityManager -> { @@ -246,6 +250,7 @@ public void testUpdateMultipleAggregateMembers() { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonComponentUpdate.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.do not support") public void testUpdateAllAggregateMembers() { sessionFactoryScope().inTransaction( entityManager -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/JsonWithArrayEmbeddableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/JsonWithArrayEmbeddableTest.java index be84f182a45b..2c7569f38bf5 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/JsonWithArrayEmbeddableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/JsonWithArrayEmbeddableTest.java @@ -20,6 +20,7 @@ import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.testing.orm.junit.SkipForDialect; @@ -219,6 +220,7 @@ public void testUpdateAggregate(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonComponentUpdate.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.do not support") public void testUpdateAggregateMember(SessionFactoryScope scope) { scope.inTransaction( entityManager -> { @@ -232,6 +234,7 @@ public void testUpdateAggregateMember(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonComponentUpdate.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.do not support") public void testUpdateMultipleAggregateMembers(SessionFactoryScope scope) { scope.inTransaction( entityManager -> { @@ -247,6 +250,7 @@ public void testUpdateMultipleAggregateMembers(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonComponentUpdate.class) @SkipForDialect( dialectClass = OracleDialect.class, reason = "External driver fix required") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.do not support") public void testUpdateAllAggregateMembers(SessionFactoryScope scope) { scope.inTransaction( entityManager -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/NestedJsonEmbeddableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/NestedJsonEmbeddableTest.java index 2f5d880bcad5..61cf0570ac1d 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/NestedJsonEmbeddableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/NestedJsonEmbeddableTest.java @@ -20,6 +20,7 @@ import java.util.UUID; import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.type.SqlTypes; import org.hibernate.testing.orm.domain.gambit.EntityOfBasics; @@ -28,6 +29,7 @@ import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.Jira; import org.hibernate.testing.orm.junit.RequiresDialectFeature; +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; @@ -47,7 +49,7 @@ public class NestedJsonEmbeddableTest extends BaseSessionFactoryFunctionalTest { @Override protected Class[] getAnnotatedClasses() { return new Class[] { - JsonHolder.class + JsonHolder.class }; } @@ -55,8 +57,20 @@ protected Class[] getAnnotatedClasses() { public void setUp() { inTransaction( session -> { - session.persist( new JsonHolder( 1L, "XYZ", 10, "String \"A&B\"", EmbeddableAggregate.createAggregate1() ) ); - session.persist( new JsonHolder( 2L, null, 20, "String 'abc'", EmbeddableAggregate.createAggregate2() ) ); + session.persist( new JsonHolder( + 1L, + "XYZ", + 10, + "String \"A&B\"", + EmbeddableAggregate.createAggregate1() + ) ); + session.persist( new JsonHolder( + 2L, + null, + 20, + "String 'abc'", + EmbeddableAggregate.createAggregate2() + ) ); } ); } @@ -71,6 +85,7 @@ protected void cleanupTest() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testUpdate() { sessionFactoryScope().inTransaction( entityManager -> { @@ -87,26 +102,37 @@ public void testUpdate() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testFetch() { sessionFactoryScope().inSession( entityManager -> { - List jsonHolders = entityManager.createQuery( "from JsonHolder b where b.id = 1", JsonHolder.class ).getResultList(); + List jsonHolders = entityManager.createQuery( + "from JsonHolder b where b.id = 1", + JsonHolder.class + ).getResultList(); assertEquals( 1, jsonHolders.size() ); JsonHolder jsonHolder = jsonHolders.get( 0 ); assertEquals( 1L, jsonHolder.getId() ); assertEquals( "XYZ", jsonHolder.theJson.stringField ); assertEquals( 10, jsonHolder.theJson.simpleEmbeddable.integerField ); - assertEquals( "String \"A&B\"", jsonHolder.theJson.simpleEmbeddable.doubleNested.theNested.theLeaf.stringField ); + assertEquals( + "String \"A&B\"", + jsonHolder.theJson.simpleEmbeddable.doubleNested.theNested.theLeaf.stringField + ); assertStructEquals( EmbeddableAggregate.createAggregate1(), jsonHolder.getAggregate() ); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testFetchNull() { sessionFactoryScope().inSession( entityManager -> { - List jsonHolders = entityManager.createQuery( "from JsonHolder b where b.id = 2", JsonHolder.class ).getResultList(); + List jsonHolders = entityManager.createQuery( + "from JsonHolder b where b.id = 2", + JsonHolder.class + ).getResultList(); assertEquals( 1, jsonHolders.size() ); JsonHolder jsonHolder = jsonHolders.get( 0 ); assertEquals( 2L, jsonHolder.getId() ); @@ -118,15 +144,22 @@ public void testFetchNull() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testDomainResult() { sessionFactoryScope().inSession( entityManager -> { - List structs = entityManager.createQuery( "select b.theJson from JsonHolder b where b.id = 1", TheJson.class ).getResultList(); + List structs = entityManager.createQuery( + "select b.theJson from JsonHolder b where b.id = 1", + TheJson.class + ).getResultList(); assertEquals( 1, structs.size() ); TheJson theJson = structs.get( 0 ); assertEquals( "XYZ", theJson.stringField ); assertEquals( 10, theJson.simpleEmbeddable.integerField ); - assertEquals( "String \"A&B\"", theJson.simpleEmbeddable.doubleNested.theNested.theLeaf.stringField ); + assertEquals( + "String \"A&B\"", + theJson.simpleEmbeddable.doubleNested.theNested.theLeaf.stringField + ); assertStructEquals( EmbeddableAggregate.createAggregate1(), theJson.nested ); } ); @@ -205,16 +238,21 @@ public void testSelectionItems() { assertEquals( simpleEmbeddable.doubleNested.theNested, tuple.get( 27, Nested.class ) ); assertEquals( simpleEmbeddable.doubleNested.theNested.theLeaf, tuple.get( 28, Leaf.class ) ); assertEquals( 10, simpleEmbeddable.integerField ); - assertEquals( "String \"A&B\"", simpleEmbeddable.doubleNested.theNested.theLeaf.stringField ); + assertEquals( + "String \"A&B\"", + simpleEmbeddable.doubleNested.theNested.theLeaf.stringField + ); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testDeleteWhere() { sessionFactoryScope().inTransaction( entityManager -> { - entityManager.createMutationQuery( "delete JsonHolder b where b.theJson is not null" ).executeUpdate(); + entityManager.createMutationQuery( "delete JsonHolder b where b.theJson is not null" ) + .executeUpdate(); assertNull( entityManager.find( JsonHolder.class, 1L ) ); } @@ -222,6 +260,7 @@ public void testDeleteWhere() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testUpdateAggregate() { sessionFactoryScope().inTransaction( entityManager -> { @@ -232,31 +271,39 @@ public void testUpdateAggregate() { } @Test - @Jira( "https://hibernate.atlassian.net/browse/HHH-17695" ) + @Jira("https://hibernate.atlassian.net/browse/HHH-17695") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNullNestedAggregate() { sessionFactoryScope().inTransaction( - entityManager -> { - JsonHolder jsonHolder = new JsonHolder(3L, "abc", 30, "String 'xyz'", null ); - entityManager.persist( jsonHolder ); - } + entityManager -> { + JsonHolder jsonHolder = new JsonHolder( 3L, "abc", 30, "String 'xyz'", null ); + entityManager.persist( jsonHolder ); + } ); sessionFactoryScope().inTransaction( entityManager -> { - JsonHolder jsonHolder = entityManager.createQuery( "from JsonHolder b where b.id = 3", JsonHolder.class ).getSingleResult(); + JsonHolder jsonHolder = entityManager.createQuery( + "from JsonHolder b where b.id = 3", + JsonHolder.class + ).getSingleResult(); assertEquals( "abc", jsonHolder.theJson.stringField ); assertEquals( 30, jsonHolder.theJson.simpleEmbeddable.integerField ); - assertEquals( "String 'xyz'", jsonHolder.theJson.simpleEmbeddable.doubleNested.theNested.theLeaf.stringField ); + assertEquals( + "String 'xyz'", + jsonHolder.theJson.simpleEmbeddable.doubleNested.theNested.theLeaf.stringField + ); assertNull( jsonHolder.getAggregate() ); } ); } @Test - @Jira( "https://hibernate.atlassian.net/browse/HHH-17695" ) + @Jira("https://hibernate.atlassian.net/browse/HHH-17695") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNullNestedEmbeddable() { sessionFactoryScope().inTransaction( entityManager -> { - JsonHolder jsonHolder = new JsonHolder( ); + JsonHolder jsonHolder = new JsonHolder(); jsonHolder.setId( 3L ); jsonHolder.setTheJson( new TheJson( "abc", null, EmbeddableAggregate.createAggregate1() ) ); entityManager.persist( jsonHolder ); @@ -264,7 +311,10 @@ public void testNullNestedEmbeddable() { ); sessionFactoryScope().inTransaction( entityManager -> { - JsonHolder jsonHolder = entityManager.createQuery( "from JsonHolder b where b.id = 3", JsonHolder.class ).getSingleResult(); + JsonHolder jsonHolder = entityManager.createQuery( + "from JsonHolder b where b.id = 3", + JsonHolder.class + ).getSingleResult(); assertEquals( "abc", jsonHolder.theJson.stringField ); assertNull( jsonHolder.theJson.simpleEmbeddable ); assertStructEquals( EmbeddableAggregate.createAggregate1(), jsonHolder.getAggregate() ); @@ -273,11 +323,12 @@ public void testNullNestedEmbeddable() { } @Test - @Jira( "https://hibernate.atlassian.net/browse/HHH-17695" ) + @Jira("https://hibernate.atlassian.net/browse/HHH-17695") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNullNestedEmbeddableAndAggregate() { sessionFactoryScope().inTransaction( entityManager -> { - JsonHolder jsonHolder = new JsonHolder( ); + JsonHolder jsonHolder = new JsonHolder(); jsonHolder.setId( 3L ); jsonHolder.setTheJson( new TheJson( "abc", null, null ) ); entityManager.persist( jsonHolder ); @@ -285,7 +336,10 @@ public void testNullNestedEmbeddableAndAggregate() { ); sessionFactoryScope().inTransaction( entityManager -> { - JsonHolder jsonHolder = entityManager.createQuery( "from JsonHolder b where b.id = 3", JsonHolder.class ).getSingleResult(); + JsonHolder jsonHolder = entityManager.createQuery( + "from JsonHolder b where b.id = 3", + JsonHolder.class + ).getSingleResult(); assertEquals( "abc", jsonHolder.theJson.stringField ); assertNull( jsonHolder.theJson.simpleEmbeddable ); assertNull( jsonHolder.getAggregate() ); @@ -295,10 +349,12 @@ public void testNullNestedEmbeddableAndAggregate() { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonComponentUpdate.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not suppported") public void testUpdateAggregateMember() { sessionFactoryScope().inTransaction( entityManager -> { - entityManager.createMutationQuery( "update JsonHolder b set b.theJson.nested.theString = null" ).executeUpdate(); + entityManager.createMutationQuery( "update JsonHolder b set b.theJson.nested.theString = null" ) + .executeUpdate(); EmbeddableAggregate struct = EmbeddableAggregate.createAggregate1(); struct.setTheString( null ); assertStructEquals( struct, entityManager.find( JsonHolder.class, 1L ).getAggregate() ); @@ -308,10 +364,13 @@ public void testUpdateAggregateMember() { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonComponentUpdate.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not suppported") public void testUpdateMultipleAggregateMembers() { sessionFactoryScope().inTransaction( entityManager -> { - entityManager.createMutationQuery( "update JsonHolder b set b.theJson.nested.theString = null, b.theJson.nested.theUuid = null" ).executeUpdate(); + entityManager.createMutationQuery( + "update JsonHolder b set b.theJson.nested.theString = null, b.theJson.nested.theUuid = null" ) + .executeUpdate(); EmbeddableAggregate struct = EmbeddableAggregate.createAggregate1(); struct.setTheString( null ); struct.setTheUuid( null ); @@ -322,40 +381,41 @@ public void testUpdateMultipleAggregateMembers() { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonComponentUpdate.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testUpdateAllAggregateMembers() { sessionFactoryScope().inTransaction( entityManager -> { EmbeddableAggregate struct = EmbeddableAggregate.createAggregate1(); entityManager.createMutationQuery( - "update JsonHolder b set " + - "b.theJson.nested.theInt = :theInt," + - "b.theJson.nested.theDouble = :theDouble," + - "b.theJson.nested.theBoolean = :theBoolean," + - "b.theJson.nested.theNumericBoolean = :theNumericBoolean," + - "b.theJson.nested.theStringBoolean = :theStringBoolean," + - "b.theJson.nested.theString = :theString," + - "b.theJson.nested.theInteger = :theInteger," + - "b.theJson.nested.theUrl = :theUrl," + - "b.theJson.nested.theClob = :theClob," + - "b.theJson.nested.theBinary = :theBinary," + - "b.theJson.nested.theDate = :theDate," + - "b.theJson.nested.theTime = :theTime," + - "b.theJson.nested.theTimestamp = :theTimestamp," + - "b.theJson.nested.theInstant = :theInstant," + - "b.theJson.nested.theUuid = :theUuid," + - "b.theJson.nested.gender = :gender," + - "b.theJson.nested.convertedGender = :convertedGender," + - "b.theJson.nested.ordinalGender = :ordinalGender," + - "b.theJson.nested.theDuration = :theDuration," + - "b.theJson.nested.theLocalDateTime = :theLocalDateTime," + - "b.theJson.nested.theLocalDate = :theLocalDate," + - "b.theJson.nested.theLocalTime = :theLocalTime," + - "b.theJson.nested.theZonedDateTime = :theZonedDateTime," + - "b.theJson.nested.theOffsetDateTime = :theOffsetDateTime," + - "b.theJson.nested.mutableValue = :mutableValue," + - "b.theJson.simpleEmbeddable.integerField = :integerField " + - "where b.id = 2" - ) + "update JsonHolder b set " + + "b.theJson.nested.theInt = :theInt," + + "b.theJson.nested.theDouble = :theDouble," + + "b.theJson.nested.theBoolean = :theBoolean," + + "b.theJson.nested.theNumericBoolean = :theNumericBoolean," + + "b.theJson.nested.theStringBoolean = :theStringBoolean," + + "b.theJson.nested.theString = :theString," + + "b.theJson.nested.theInteger = :theInteger," + + "b.theJson.nested.theUrl = :theUrl," + + "b.theJson.nested.theClob = :theClob," + + "b.theJson.nested.theBinary = :theBinary," + + "b.theJson.nested.theDate = :theDate," + + "b.theJson.nested.theTime = :theTime," + + "b.theJson.nested.theTimestamp = :theTimestamp," + + "b.theJson.nested.theInstant = :theInstant," + + "b.theJson.nested.theUuid = :theUuid," + + "b.theJson.nested.gender = :gender," + + "b.theJson.nested.convertedGender = :convertedGender," + + "b.theJson.nested.ordinalGender = :ordinalGender," + + "b.theJson.nested.theDuration = :theDuration," + + "b.theJson.nested.theLocalDateTime = :theLocalDateTime," + + "b.theJson.nested.theLocalDate = :theLocalDate," + + "b.theJson.nested.theLocalTime = :theLocalTime," + + "b.theJson.nested.theZonedDateTime = :theZonedDateTime," + + "b.theJson.nested.theOffsetDateTime = :theOffsetDateTime," + + "b.theJson.nested.mutableValue = :mutableValue," + + "b.theJson.simpleEmbeddable.integerField = :integerField " + + "where b.id = 2" + ) .setParameter( "theInt", struct.getTheInt() ) .setParameter( "theDouble", struct.getTheDouble() ) .setParameter( "theBoolean", struct.isTheBoolean() ) @@ -407,7 +467,12 @@ public static class JsonHolder { public JsonHolder() { } - public JsonHolder(Long id, String stringField, Integer integerField, String leaf, EmbeddableAggregate aggregate) { + public JsonHolder( + Long id, + String stringField, + Integer integerField, + String leaf, + EmbeddableAggregate aggregate) { this.id = id; this.theJson = new TheJson( stringField, integerField, leaf, aggregate ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/NestedXmlEmbeddableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/NestedXmlEmbeddableTest.java index 646467105b64..d2831df3eb40 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/NestedXmlEmbeddableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/NestedXmlEmbeddableTest.java @@ -9,6 +9,7 @@ import jakarta.persistence.Id; import jakarta.persistence.Tuple; import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.OracleDialect; import org.hibernate.testing.orm.domain.gambit.EntityOfBasics; import org.hibernate.testing.orm.domain.gambit.MutableValue; @@ -135,6 +136,7 @@ public void testDomainResult() { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.argument of XMLTABLE must be type xmltype, not type xml") public void testSelectionItems() { sessionFactoryScope().inSession( entityManager -> { @@ -297,6 +299,7 @@ public void testNullNestedEmbeddableAndAggregate() { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlComponentUpdate.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.argument of XMLTABLE must be type xmltype, not type xml") public void testUpdateAggregateMember() { sessionFactoryScope().inTransaction( entityManager -> { @@ -310,6 +313,7 @@ public void testUpdateAggregateMember() { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlComponentUpdate.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.argument of XMLTABLE must be type xmltype, not type xml") public void testUpdateAggregateMemberOnNestedNull() { sessionFactoryScope().inTransaction( entityManager -> { @@ -322,6 +326,7 @@ public void testUpdateAggregateMemberOnNestedNull() { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlComponentUpdate.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.argument of XMLTABLE must be type xmltype, not type xml") public void testUpdateMultipleAggregateMembers() { sessionFactoryScope().inTransaction( entityManager -> { @@ -336,6 +341,7 @@ public void testUpdateMultipleAggregateMembers() { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlComponentUpdate.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.argument of XMLTABLE must be type xmltype, not type xml") public void testUpdateAllAggregateMembers() { sessionFactoryScope().inTransaction( entityManager -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/UpdateEntityWithIdClassAndJsonFieldTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/UpdateEntityWithIdClassAndJsonFieldTest.java index c204a240e66d..d0bfd1cff803 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/UpdateEntityWithIdClassAndJsonFieldTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/UpdateEntityWithIdClassAndJsonFieldTest.java @@ -8,6 +8,8 @@ import java.util.Objects; import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.dialect.GaussDBDialect; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.hibernate.type.SqlTypes; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -54,6 +56,7 @@ public void setUp(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.operator does not exist: jsonb || jsonb") public void updateTest(SessionFactoryScope scope) { scope.inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/XmlEmbeddableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/XmlEmbeddableTest.java index 223bfd366b09..14b796e96af1 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/XmlEmbeddableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/XmlEmbeddableTest.java @@ -4,23 +4,6 @@ */ package org.hibernate.orm.test.mapping.embeddable; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Tuple; -import org.hibernate.annotations.JdbcTypeCode; -import org.hibernate.dialect.OracleDialect; -import org.hibernate.testing.orm.domain.gambit.EntityOfBasics; -import org.hibernate.testing.orm.domain.gambit.MutableValue; -import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest; -import org.hibernate.testing.orm.junit.DialectFeatureChecks; -import org.hibernate.testing.orm.junit.JiraKey; -import org.hibernate.testing.orm.junit.RequiresDialectFeature; -import org.hibernate.testing.orm.junit.SkipForDialect; -import org.hibernate.type.SqlTypes; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - import java.net.URL; import java.sql.Time; import java.sql.Timestamp; @@ -35,6 +18,26 @@ import java.util.List; import java.util.UUID; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.dialect.GaussDBDialect; +import org.hibernate.dialect.OracleDialect; +import org.hibernate.type.SqlTypes; + +import org.hibernate.testing.orm.domain.gambit.EntityOfBasics; +import org.hibernate.testing.orm.domain.gambit.MutableValue; +import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest; +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +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; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Tuple; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -46,7 +49,7 @@ public class XmlEmbeddableTest extends BaseSessionFactoryFunctionalTest { @Override protected Class[] getAnnotatedClasses() { return new Class[] { - XmlHolder.class + XmlHolder.class }; } @@ -70,6 +73,7 @@ protected void cleanupTest() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testUpdate() { sessionFactoryScope().inTransaction( entityManager -> { @@ -77,13 +81,17 @@ public void testUpdate() { XmlHolder.setAggregate( EmbeddableAggregate.createAggregate2() ); entityManager.flush(); entityManager.clear(); - EmbeddableAggregate.assertEquals( EmbeddableAggregate.createAggregate2(), entityManager.find( XmlHolder.class, 1L ).getAggregate() ); + EmbeddableAggregate.assertEquals( + EmbeddableAggregate.createAggregate2(), + entityManager.find( XmlHolder.class, 1L ).getAggregate() + ); } ); } @Test - @JiraKey( "HHH-16682" ) + @JiraKey("HHH-16682") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testDirtyChecking() { sessionFactoryScope().inTransaction( entityManager -> { @@ -97,34 +105,52 @@ public void testDirtyChecking() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testFetch() { sessionFactoryScope().inSession( entityManager -> { - List XmlHolders = entityManager.createQuery( "from XmlHolder b where b.id = 1", XmlHolder.class ).getResultList(); + List XmlHolders = entityManager.createQuery( + "from XmlHolder b where b.id = 1", + XmlHolder.class + ).getResultList(); assertEquals( 1, XmlHolders.size() ); assertEquals( 1L, XmlHolders.get( 0 ).getId() ); - EmbeddableAggregate.assertEquals( EmbeddableAggregate.createAggregate1(), XmlHolders.get( 0 ).getAggregate() ); + EmbeddableAggregate.assertEquals( + EmbeddableAggregate.createAggregate1(), + XmlHolders.get( 0 ).getAggregate() + ); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testFetchNull() { sessionFactoryScope().inSession( entityManager -> { - List xmlHolders = entityManager.createQuery( "from XmlHolder b where b.id = 2", XmlHolder.class ).getResultList(); + List xmlHolders = entityManager.createQuery( + "from XmlHolder b where b.id = 2", + XmlHolder.class + ).getResultList(); assertEquals( 1, xmlHolders.size() ); assertEquals( 2L, xmlHolders.get( 0 ).getId() ); - EmbeddableAggregate.assertEquals( EmbeddableAggregate.createAggregate2(), xmlHolders.get( 0 ).getAggregate() ); + EmbeddableAggregate.assertEquals( + EmbeddableAggregate.createAggregate2(), + xmlHolders.get( 0 ).getAggregate() + ); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testDomainResult() { sessionFactoryScope().inSession( entityManager -> { - List structs = entityManager.createQuery( "select b.aggregate from XmlHolder b where b.id = 1", EmbeddableAggregate.class ).getResultList(); + List structs = entityManager.createQuery( + "select b.aggregate from XmlHolder b where b.id = 1", + EmbeddableAggregate.class + ).getResultList(); assertEquals( 1, structs.size() ); EmbeddableAggregate.assertEquals( EmbeddableAggregate.createAggregate1(), structs.get( 0 ) ); } @@ -132,6 +158,7 @@ public void testDomainResult() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not supported") public void testSelectionItems() { sessionFactoryScope().inSession( entityManager -> { @@ -199,10 +226,12 @@ public void testSelectionItems() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testDeleteWhere() { sessionFactoryScope().inTransaction( entityManager -> { - entityManager.createMutationQuery( "delete XmlHolder b where b.aggregate is not null" ).executeUpdate(); + entityManager.createMutationQuery( "delete XmlHolder b where b.aggregate is not null" ) + .executeUpdate(); assertNull( entityManager.find( XmlHolder.class, 1L ) ); } @@ -210,6 +239,7 @@ public void testDeleteWhere() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testUpdateAggregate() { sessionFactoryScope().inTransaction( entityManager -> { @@ -221,33 +251,45 @@ public void testUpdateAggregate() { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlComponentUpdate.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not supported") public void testUpdateAggregateMember() { sessionFactoryScope().inTransaction( entityManager -> { - entityManager.createMutationQuery( "update XmlHolder b set b.aggregate.theString = null" ).executeUpdate(); + entityManager.createMutationQuery( "update XmlHolder b set b.aggregate.theString = null" ) + .executeUpdate(); EmbeddableAggregate struct = EmbeddableAggregate.createAggregate1(); struct.setTheString( null ); - EmbeddableAggregate.assertEquals( struct, entityManager.find( XmlHolder.class, 1L ).getAggregate() ); + EmbeddableAggregate.assertEquals( + struct, + entityManager.find( XmlHolder.class, 1L ).getAggregate() + ); } ); } @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlComponentUpdate.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not supported") public void testUpdateMultipleAggregateMembers() { sessionFactoryScope().inTransaction( entityManager -> { - entityManager.createMutationQuery( "update XmlHolder b set b.aggregate.theString = null, b.aggregate.theUuid = null" ).executeUpdate(); + entityManager.createMutationQuery( + "update XmlHolder b set b.aggregate.theString = null, b.aggregate.theUuid = null" ) + .executeUpdate(); EmbeddableAggregate struct = EmbeddableAggregate.createAggregate1(); struct.setTheString( null ); struct.setTheUuid( null ); - EmbeddableAggregate.assertEquals( struct, entityManager.find( XmlHolder.class, 1L ).getAggregate() ); + EmbeddableAggregate.assertEquals( + struct, + entityManager.find( XmlHolder.class, 1L ).getAggregate() + ); } ); } @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlComponentUpdate.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testUpdateAllAggregateMembers() { sessionFactoryScope().inTransaction( entityManager -> { @@ -307,7 +349,10 @@ public void testUpdateAllAggregateMembers() { .setParameter( "theOffsetDateTime", struct.getTheOffsetDateTime() ) .setParameter( "mutableValue", struct.getMutableValue() ) .executeUpdate(); - EmbeddableAggregate.assertEquals( EmbeddableAggregate.createAggregate1(), entityManager.find( XmlHolder.class, 2L ).getAggregate() ); + EmbeddableAggregate.assertEquals( + EmbeddableAggregate.createAggregate1(), + entityManager.find( XmlHolder.class, 2L ).getAggregate() + ); } ); } @@ -348,7 +393,7 @@ public void setAggregate(EmbeddableAggregate aggregate) { this.aggregate = aggregate; } - //tag::embeddable-xml-type-mapping-example[] + //tag::embeddable-xml-type-mapping-example[] } //end::embeddable-xml-type-mapping-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/XmlWithArrayEmbeddableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/XmlWithArrayEmbeddableTest.java index e555c72d4024..686076790fb6 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/XmlWithArrayEmbeddableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/embeddable/XmlWithArrayEmbeddableTest.java @@ -4,12 +4,26 @@ */ package org.hibernate.orm.test.mapping.embeddable; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Tuple; +import java.net.URL; +import java.sql.Time; +import java.sql.Timestamp; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.ZonedDateTime; +import java.util.Date; +import java.util.List; +import java.util.UUID; + import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.OracleDialect; +import org.hibernate.type.SqlTypes; + import org.hibernate.testing.jdbc.SharedDriverManagerTypeCacheClearingIntegrator; import org.hibernate.testing.orm.domain.gambit.EntityOfBasics; import org.hibernate.testing.orm.domain.gambit.MutableValue; @@ -23,24 +37,13 @@ import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; import org.hibernate.testing.orm.junit.SkipForDialect; -import org.hibernate.type.SqlTypes; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.net.URL; -import java.sql.Time; -import java.sql.Timestamp; -import java.time.Duration; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.ZonedDateTime; -import java.util.Date; -import java.util.List; -import java.util.UUID; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Tuple; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -80,6 +83,7 @@ protected void cleanupTest(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testUpdate(SessionFactoryScope scope) { scope.inTransaction( entityManager -> { @@ -87,47 +91,72 @@ public void testUpdate(SessionFactoryScope scope) { XmlHolder.setAggregate( EmbeddableWithArrayAggregate.createAggregate2() ); entityManager.flush(); entityManager.clear(); - EmbeddableWithArrayAggregate.assertEquals( EmbeddableWithArrayAggregate.createAggregate2(), entityManager.find( XmlHolder.class, 1L ).getAggregate() ); + EmbeddableWithArrayAggregate.assertEquals( + EmbeddableWithArrayAggregate.createAggregate2(), + entityManager.find( XmlHolder.class, 1L ).getAggregate() + ); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testFetch(SessionFactoryScope scope) { scope.inSession( entityManager -> { - List XmlHolders = entityManager.createQuery( "from XmlHolder b where b.id = 1", XmlHolder.class ).getResultList(); + List XmlHolders = entityManager.createQuery( + "from XmlHolder b where b.id = 1", + XmlHolder.class + ).getResultList(); assertEquals( 1, XmlHolders.size() ); assertEquals( 1L, XmlHolders.get( 0 ).getId() ); - EmbeddableWithArrayAggregate.assertEquals( EmbeddableWithArrayAggregate.createAggregate1(), XmlHolders.get( 0 ).getAggregate() ); + EmbeddableWithArrayAggregate.assertEquals( + EmbeddableWithArrayAggregate.createAggregate1(), + XmlHolders.get( 0 ).getAggregate() + ); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testFetchNull(SessionFactoryScope scope) { scope.inSession( entityManager -> { - List XmlHolders = entityManager.createQuery( "from XmlHolder b where b.id = 2", XmlHolder.class ).getResultList(); + List XmlHolders = entityManager.createQuery( + "from XmlHolder b where b.id = 2", + XmlHolder.class + ).getResultList(); assertEquals( 1, XmlHolders.size() ); assertEquals( 2L, XmlHolders.get( 0 ).getId() ); - EmbeddableWithArrayAggregate.assertEquals( EmbeddableWithArrayAggregate.createAggregate2(), XmlHolders.get( 0 ).getAggregate() ); + EmbeddableWithArrayAggregate.assertEquals( + EmbeddableWithArrayAggregate.createAggregate2(), + XmlHolders.get( 0 ).getAggregate() + ); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testDomainResult(SessionFactoryScope scope) { scope.inSession( entityManager -> { - List structs = entityManager.createQuery( "select b.aggregate from XmlHolder b where b.id = 1", EmbeddableWithArrayAggregate.class ).getResultList(); + List structs = entityManager.createQuery( + "select b.aggregate from XmlHolder b where b.id = 1", + EmbeddableWithArrayAggregate.class + ).getResultList(); assertEquals( 1, structs.size() ); - EmbeddableWithArrayAggregate.assertEquals( EmbeddableWithArrayAggregate.createAggregate1(), structs.get( 0 ) ); + EmbeddableWithArrayAggregate.assertEquals( + EmbeddableWithArrayAggregate.createAggregate1(), + structs.get( 0 ) + ); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not supported") public void testSelectionItems(SessionFactoryScope scope) { scope.inSession( entityManager -> { @@ -189,16 +218,21 @@ public void testSelectionItems(SessionFactoryScope scope) { struct.setTheZonedDateTime( tuple.get( 22, ZonedDateTime[].class ) ); struct.setTheOffsetDateTime( tuple.get( 23, OffsetDateTime[].class ) ); struct.setMutableValue( tuple.get( 24, MutableValue[].class ) ); - EmbeddableWithArrayAggregate.assertEquals( EmbeddableWithArrayAggregate.createAggregate1(), struct ); + EmbeddableWithArrayAggregate.assertEquals( + EmbeddableWithArrayAggregate.createAggregate1(), + struct + ); } ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testDeleteWhere(SessionFactoryScope scope) { scope.inTransaction( entityManager -> { - entityManager.createMutationQuery( "delete XmlHolder b where b.aggregate is not null" ).executeUpdate(); + entityManager.createMutationQuery( "delete XmlHolder b where b.aggregate is not null" ) + .executeUpdate(); assertNull( entityManager.find( XmlHolder.class, 1L ) ); } @@ -206,6 +240,7 @@ public void testDeleteWhere(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testUpdateAggregate(SessionFactoryScope scope) { scope.inTransaction( entityManager -> { @@ -217,34 +252,46 @@ public void testUpdateAggregate(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlComponentUpdate.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not supported") public void testUpdateAggregateMember(SessionFactoryScope scope) { scope.inTransaction( entityManager -> { - entityManager.createMutationQuery( "update XmlHolder b set b.aggregate.theString = null" ).executeUpdate(); + entityManager.createMutationQuery( "update XmlHolder b set b.aggregate.theString = null" ) + .executeUpdate(); EmbeddableWithArrayAggregate struct = EmbeddableWithArrayAggregate.createAggregate1(); struct.setTheString( null ); - EmbeddableWithArrayAggregate.assertEquals( struct, entityManager.find( XmlHolder.class, 1L ).getAggregate() ); + EmbeddableWithArrayAggregate.assertEquals( + struct, + entityManager.find( XmlHolder.class, 1L ).getAggregate() + ); } ); } @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlComponentUpdate.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not supported") public void testUpdateMultipleAggregateMembers(SessionFactoryScope scope) { scope.inTransaction( entityManager -> { - entityManager.createMutationQuery( "update XmlHolder b set b.aggregate.theString = null, b.aggregate.theUuid = null" ).executeUpdate(); + entityManager.createMutationQuery( + "update XmlHolder b set b.aggregate.theString = null, b.aggregate.theUuid = null" ) + .executeUpdate(); EmbeddableWithArrayAggregate struct = EmbeddableWithArrayAggregate.createAggregate1(); struct.setTheString( null ); struct.setTheUuid( null ); - EmbeddableWithArrayAggregate.assertEquals( struct, entityManager.find( XmlHolder.class, 1L ).getAggregate() ); + EmbeddableWithArrayAggregate.assertEquals( + struct, + entityManager.find( XmlHolder.class, 1L ).getAggregate() + ); } ); } @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsXmlComponentUpdate.class) - @SkipForDialect( dialectClass = OracleDialect.class, reason = "External driver fix required") + @SkipForDialect(dialectClass = OracleDialect.class, reason = "External driver fix required") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.not supported") public void testUpdateAllAggregateMembers(SessionFactoryScope scope) { scope.inTransaction( entityManager -> { @@ -304,7 +351,10 @@ public void testUpdateAllAggregateMembers(SessionFactoryScope scope) { .setParameter( "theOffsetDateTime", struct.getTheOffsetDateTime() ) .setParameter( "mutableValue", struct.getMutableValue() ) .executeUpdate(); - EmbeddableWithArrayAggregate.assertEquals( EmbeddableWithArrayAggregate.createAggregate1(), entityManager.find( XmlHolder.class, 2L ).getAggregate() ); + EmbeddableWithArrayAggregate.assertEquals( + EmbeddableWithArrayAggregate.createAggregate1(), + entityManager.find( XmlHolder.class, 2L ).getAggregate() + ); } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/DefaultGeneratedValueIdentityTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/DefaultGeneratedValueIdentityTest.java index eb2226c52227..c16aa3db27a8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/DefaultGeneratedValueIdentityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/DefaultGeneratedValueIdentityTest.java @@ -28,6 +28,7 @@ import org.hibernate.annotations.UpdateTimestamp; import org.hibernate.annotations.ValueGenerationType; import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.generator.EventType; import org.hibernate.generator.OnExecutionGenerator; @@ -37,6 +38,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.Test; @@ -50,16 +52,17 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsIdentityColumns.class) -@RequiresDialectFeature( feature = DialectFeatureChecks.CurrentTimestampHasMicrosecondPrecision.class ) -@RequiresDialectFeature( feature = DialectFeatureChecks.UsesStandardCurrentTimestampFunction.class ) -@DomainModel( annotatedClasses = DefaultGeneratedValueIdentityTest.TheEntity.class ) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.CurrentTimestampHasMicrosecondPrecision.class) +@RequiresDialectFeature(feature = DialectFeatureChecks.UsesStandardCurrentTimestampFunction.class) +@DomainModel(annotatedClasses = DefaultGeneratedValueIdentityTest.TheEntity.class) @SessionFactory @SuppressWarnings("JUnitMalformedDeclaration") public class DefaultGeneratedValueIdentityTest { @Test - @JiraKey( "HHH-12671" ) + @JiraKey("HHH-12671") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testGenerationWithIdentityInsert(SessionFactoryScope scope) { final TheEntity theEntity = new TheEntity(); @@ -137,20 +140,20 @@ public void dropTestData(SessionFactoryScope scope) { scope.inTransaction( (s) -> s.createQuery( "delete TheEntity" ).executeUpdate() ); } - @Entity( name = "TheEntity" ) + @Entity(name = "TheEntity") public static class TheEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Generated - @ColumnDefault( "CURRENT_TIMESTAMP" ) - @Column( nullable = false ) + @ColumnDefault("CURRENT_TIMESTAMP") + @Column(nullable = false) private Date createdDate; - @Generated(event = { EventType.INSERT, EventType.UPDATE}) - @ColumnDefault( "CURRENT_TIMESTAMP" ) - @Column( nullable = false ) + @Generated(event = { EventType.INSERT, EventType.UPDATE }) + @ColumnDefault("CURRENT_TIMESTAMP") + @Column(nullable = false) private Calendar alwaysDate; @CreationTimestamp diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateIdentityTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateIdentityTest.java index 962155c883ca..cdf6ec0fc257 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateIdentityTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateIdentityTest.java @@ -14,6 +14,7 @@ import org.hibernate.annotations.SourceType; import org.hibernate.annotations.UpdateTimestamp; import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.PersistenceContext; @@ -35,6 +36,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.hibernate.testing.orm.logger.LoggerInspectionExtension; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -56,18 +58,19 @@ * * @author Marco Belladelli */ -@DomainModel( annotatedClasses = { +@DomainModel(annotatedClasses = { MutationDelegateIdentityTest.IdentityOnly.class, MutationDelegateIdentityTest.IdentityAndValues.class, MutationDelegateIdentityTest.IdentityAndValuesAndRowId.class, MutationDelegateIdentityTest.IdentityAndValuesAndRowIdAndNaturalId.class, -} ) -@SessionFactory( useCollectingStatementInspector = true ) -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsIdentityColumns.class ) +}) +@SessionFactory(useCollectingStatementInspector = true) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) // Batch size is only enabled to make sure it's ignored when using mutation delegates -@ServiceRegistry( settings = @Setting( name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "5" ) ) +@ServiceRegistry(settings = @Setting(name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "5")) public class MutationDelegateIdentityTest { @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testInsertGeneratedIdentityOnly(SessionFactoryScope scope) { final GeneratedValuesMutationDelegate delegate = getDelegate( scope, IdentityOnly.class, MutationType.INSERT ); final SQLStatementInspector inspector = scope.getCollectingStatementInspector(); @@ -88,6 +91,7 @@ public void testInsertGeneratedIdentityOnly(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testInsertGeneratedValuesAndIdentity(SessionFactoryScope scope) { final GeneratedValuesMutationDelegate delegate = getDelegate( scope, @@ -115,6 +119,7 @@ public void testInsertGeneratedValuesAndIdentity(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testUpdateGeneratedValuesAndIdentity(SessionFactoryScope scope) { final GeneratedValuesMutationDelegate delegate = getDelegate( scope, @@ -147,6 +152,7 @@ public void testUpdateGeneratedValuesAndIdentity(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testInsertGeneratedValuesAndIdentityAndRowId(SessionFactoryScope scope) { final GeneratedValuesMutationDelegate delegate = getDelegate( scope, @@ -198,6 +204,7 @@ public void testInsertGeneratedValuesAndIdentityAndRowId(SessionFactoryScope sco } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testInsertGeneratedValuesAndIdentityAndRowIdAndNaturalId(SessionFactoryScope scope) { final GeneratedValuesMutationDelegate delegate = getDelegate( scope, @@ -252,7 +259,11 @@ private static GeneratedValuesMutationDelegate getDelegate( @RegisterExtension public LoggerInspectionExtension logger = LoggerInspectionExtension.builder().setLogger( - Logger.getMessageLogger( MethodHandles.lookup(), CoreMessageLogger.class, SqlExceptionHelper.class.getName() ) + Logger.getMessageLogger( + MethodHandles.lookup(), + CoreMessageLogger.class, + SqlExceptionHelper.class.getName() + ) ).build(); @BeforeAll @@ -261,10 +272,10 @@ public void setUp(SessionFactoryScope scope) { triggerable.reset(); } - @Entity( name = "IdentityOnly" ) + @Entity(name = "IdentityOnly") public static class IdentityOnly { @Id - @GeneratedValue( strategy = GenerationType.IDENTITY ) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @@ -278,18 +289,18 @@ public String getName() { } } - @Entity( name = "IdentityAndValues" ) - @SuppressWarnings( "unused" ) + @Entity(name = "IdentityAndValues") + @SuppressWarnings("unused") public static class IdentityAndValues { @Id - @GeneratedValue( strategy = GenerationType.IDENTITY ) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Generated( event = EventType.INSERT ) - @ColumnDefault( "'default_name'" ) + @Generated(event = EventType.INSERT) + @ColumnDefault("'default_name'") private String name; - @UpdateTimestamp( source = SourceType.DB ) + @UpdateTimestamp(source = SourceType.DB) private Date updateDate; private String data; @@ -312,19 +323,19 @@ public void setData(String data) { } @RowId - @Entity( name = "IdentityAndValuesAndRowId" ) - @SuppressWarnings( "unused" ) + @Entity(name = "IdentityAndValuesAndRowId") + @SuppressWarnings("unused") public static class IdentityAndValuesAndRowId { @Id - @Column( name = "id_column" ) - @GeneratedValue( strategy = GenerationType.IDENTITY ) + @Column(name = "id_column") + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Generated( event = EventType.INSERT ) - @ColumnDefault( "'default_name'" ) + @Generated(event = EventType.INSERT) + @ColumnDefault("'default_name'") private String name; - @UpdateTimestamp( source = SourceType.DB ) + @UpdateTimestamp(source = SourceType.DB) private Date updateDate; private String data; @@ -347,16 +358,16 @@ public void setData(String data) { } @RowId - @Entity( name = "IdentityAndValuesAndRowIdAndNaturalId" ) - @SuppressWarnings( "unused" ) + @Entity(name = "IdentityAndValuesAndRowIdAndNaturalId") + @SuppressWarnings("unused") public static class IdentityAndValuesAndRowIdAndNaturalId { @Id - @Column( name = "id_column" ) - @GeneratedValue( strategy = GenerationType.IDENTITY ) + @Column(name = "id_column") + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Generated( event = EventType.INSERT ) - @ColumnDefault( "'default_name'" ) + @Generated(event = EventType.INSERT) + @ColumnDefault("'default_name'") private String name; @NaturalId diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateJoinedInheritanceTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateJoinedInheritanceTest.java index 574f509d3b4e..c3ade235fe45 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateJoinedInheritanceTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateJoinedInheritanceTest.java @@ -10,6 +10,7 @@ import org.hibernate.annotations.Generated; import org.hibernate.annotations.SourceType; import org.hibernate.annotations.UpdateTimestamp; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.generator.EventType; import org.hibernate.generator.values.GeneratedValuesMutationDelegate; import org.hibernate.id.insert.AbstractSelectingDelegate; @@ -23,6 +24,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterAll; import org.junit.jupiter.api.Test; @@ -41,14 +43,15 @@ * * @author Marco Belladelli */ -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsIdentityColumns.class ) -@DomainModel( annotatedClasses = { +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@DomainModel(annotatedClasses = { MutationDelegateJoinedInheritanceTest.BaseEntity.class, MutationDelegateJoinedInheritanceTest.ChildEntity.class, MutationDelegateJoinedInheritanceTest.NonGeneratedParent.class, MutationDelegateJoinedInheritanceTest.GeneratedChild.class, -} ) -@SessionFactory( useCollectingStatementInspector = true ) +}) +@SessionFactory(useCollectingStatementInspector = true) +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class MutationDelegateJoinedInheritanceTest { @AfterAll public void tearDown(SessionFactoryScope scope) { @@ -183,7 +186,7 @@ public void testUpdateChildEntity(SessionFactoryScope scope) { } @Test - @Jira( "https://hibernate.atlassian.net/browse/HHH-18259" ) + @Jira("https://hibernate.atlassian.net/browse/HHH-18259") public void testGeneratedOnlyOnChild(SessionFactoryScope scope) { final GeneratedValuesMutationDelegate delegate = getDelegate( scope, @@ -213,7 +216,7 @@ public void testGeneratedOnlyOnChild(SessionFactoryScope scope) { private static GeneratedValuesMutationDelegate getDelegate( SessionFactoryScope scope, - @SuppressWarnings( "SameParameterValue" ) Class entityClass, + @SuppressWarnings("SameParameterValue") Class entityClass, MutationType mutationType) { final EntityPersister entityDescriptor = scope.getSessionFactory() .getMappingMetamodel() @@ -221,22 +224,22 @@ private static GeneratedValuesMutationDelegate getDelegate( return entityDescriptor.getMutationDelegate( mutationType ); } - @Entity( name = "BaseEntity" ) - @Inheritance( strategy = InheritanceType.JOINED ) - @SuppressWarnings( "unused" ) + @Entity(name = "BaseEntity") + @Inheritance(strategy = InheritanceType.JOINED) + @SuppressWarnings("unused") public static class BaseEntity { @Id - @GeneratedValue( strategy = GenerationType.IDENTITY ) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Generated( event = EventType.INSERT ) - @ColumnDefault( "'default_name'" ) + @Generated(event = EventType.INSERT) + @ColumnDefault("'default_name'") private String name; - @UpdateTimestamp( source = SourceType.DB ) + @UpdateTimestamp(source = SourceType.DB) private Date updateDate; - @SuppressWarnings( "FieldCanBeLocal" ) + @SuppressWarnings("FieldCanBeLocal") private String data; public Long getId() { @@ -256,14 +259,14 @@ public void setData(String data) { } } - @Entity( name = "ChildEntity" ) - @SuppressWarnings( "unused" ) + @Entity(name = "ChildEntity") + @SuppressWarnings("unused") public static class ChildEntity extends BaseEntity { - @Generated( event = EventType.INSERT ) - @ColumnDefault( "'default_child_name'" ) + @Generated(event = EventType.INSERT) + @ColumnDefault("'default_child_name'") private String childName; - @UpdateTimestamp( source = SourceType.DB ) + @UpdateTimestamp(source = SourceType.DB) private Date childUpdateDate; public String getChildName() { @@ -275,9 +278,9 @@ public Date getChildUpdateDate() { } } - @Entity( name = "NonGeneratedParent" ) - @Inheritance( strategy = InheritanceType.JOINED ) - @SuppressWarnings( "unused" ) + @Entity(name = "NonGeneratedParent") + @Inheritance(strategy = InheritanceType.JOINED) + @SuppressWarnings("unused") public static class NonGeneratedParent { @Id private Long id; @@ -291,11 +294,11 @@ public void setId(Long id) { } } - @Entity( name = "GeneratedChild" ) - @SuppressWarnings( "unused" ) + @Entity(name = "GeneratedChild") + @SuppressWarnings("unused") public static class GeneratedChild extends NonGeneratedParent { - @Generated( event = EventType.INSERT ) - @ColumnDefault( "'child_name'" ) + @Generated(event = EventType.INSERT) + @ColumnDefault("'child_name'") private String name; public String getName() { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateStatementReleaseTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateStatementReleaseTest.java index 59a940b2a39e..ec95a380430f 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateStatementReleaseTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/delegate/MutationDelegateStatementReleaseTest.java @@ -12,6 +12,7 @@ import org.hibernate.annotations.Generated; import org.hibernate.annotations.SourceType; import org.hibernate.annotations.UpdateTimestamp; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.engine.jdbc.JdbcLogging; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.generator.EventType; @@ -27,6 +28,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -46,15 +48,16 @@ /** * @author Marco Belladelli */ -@DomainModel( annotatedClasses = { +@DomainModel(annotatedClasses = { MutationDelegateStatementReleaseTest.IdentityOnly.class, MutationDelegateStatementReleaseTest.IdentityAndValues.class, MutationDelegateStatementReleaseTest.BaseEntity.class, MutationDelegateStatementReleaseTest.ChildEntity.class, -} ) +}) @SessionFactory -@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsIdentityColumns.class ) -@Jira( "https://hibernate.atlassian.net/browse/HHH-17688" ) +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) +@Jira("https://hibernate.atlassian.net/browse/HHH-17688") +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class MutationDelegateStatementReleaseTest { private TriggerOnPrefixLogListener trigger; @@ -172,10 +175,10 @@ private void assertNoOrphanStatements(SessionImplementor session) { assertThat( resourceRegistry.hasRegisteredResources() ).as( "Expected no registered resources" ).isFalse(); } - @Entity( name = "IdentityOnly" ) + @Entity(name = "IdentityOnly") public static class IdentityOnly { @Id - @GeneratedValue( strategy = GenerationType.IDENTITY ) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @@ -189,18 +192,18 @@ public String getName() { } } - @Entity( name = "IdentityAndValues" ) - @SuppressWarnings( "unused" ) + @Entity(name = "IdentityAndValues") + @SuppressWarnings("unused") public static class IdentityAndValues { @Id - @GeneratedValue( strategy = GenerationType.IDENTITY ) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Generated( event = EventType.INSERT ) - @ColumnDefault( "'default_name'" ) + @Generated(event = EventType.INSERT) + @ColumnDefault("'default_name'") private String name; - @UpdateTimestamp( source = SourceType.DB ) + @UpdateTimestamp(source = SourceType.DB) private Date updateDate; private String data; @@ -222,22 +225,22 @@ public void setData(String data) { } } - @Entity( name = "BaseEntity" ) - @Inheritance( strategy = InheritanceType.JOINED ) - @SuppressWarnings( "unused" ) + @Entity(name = "BaseEntity") + @Inheritance(strategy = InheritanceType.JOINED) + @SuppressWarnings("unused") public static class BaseEntity { @Id - @GeneratedValue( strategy = GenerationType.IDENTITY ) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Generated( event = EventType.INSERT ) - @ColumnDefault( "'default_name'" ) + @Generated(event = EventType.INSERT) + @ColumnDefault("'default_name'") private String name; - @UpdateTimestamp( source = SourceType.DB ) + @UpdateTimestamp(source = SourceType.DB) private Date updateDate; - @SuppressWarnings( "FieldCanBeLocal" ) + @SuppressWarnings("FieldCanBeLocal") private String data; public Long getId() { @@ -257,14 +260,14 @@ public void setData(String data) { } } - @Entity( name = "ChildEntity" ) - @SuppressWarnings( "unused" ) + @Entity(name = "ChildEntity") + @SuppressWarnings("unused") public static class ChildEntity extends BaseEntity { - @Generated( event = EventType.INSERT ) - @ColumnDefault( "'default_child_name'" ) + @Generated(event = EventType.INSERT) + @ColumnDefault("'default_child_name'") private String childName; - @UpdateTimestamp( source = SourceType.DB ) + @UpdateTimestamp(source = SourceType.DB) private Date childUpdateDate; public String getChildName() { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/immutable/IdentityGeneratorWithNaturalIdCacheTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/immutable/IdentityGeneratorWithNaturalIdCacheTest.java index 5f6edd3e9a61..4ed58ee8b64a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/immutable/IdentityGeneratorWithNaturalIdCacheTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/naturalid/immutable/IdentityGeneratorWithNaturalIdCacheTest.java @@ -4,30 +4,31 @@ */ package org.hibernate.orm.test.mapping.naturalid.immutable; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; - import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.annotations.NaturalId; import org.hibernate.annotations.NaturalIdCache; import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.stat.spi.StatisticsImplementor; -import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.Setting; +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; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; import org.hamcrest.Matchers; import static org.hamcrest.MatcherAssert.assertThat; @@ -35,14 +36,14 @@ /** * @author Alex Burgel */ -@JiraKey( value = "HHH-11330" ) +@JiraKey(value = "HHH-11330") @ServiceRegistry( settings = { - @Setting( name = AvailableSettings.GENERATE_STATISTICS, value = "true" ), - @Setting( name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true" ) + @Setting(name = AvailableSettings.GENERATE_STATISTICS, value = "true"), + @Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true") } ) -@DomainModel( annotatedClasses = IdentityGeneratorWithNaturalIdCacheTest.Person.class ) +@DomainModel(annotatedClasses = IdentityGeneratorWithNaturalIdCacheTest.Person.class) @SessionFactory @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) public class IdentityGeneratorWithNaturalIdCacheTest { @@ -66,6 +67,7 @@ public void dropTestData(SessionFactoryScope scope) { @Test @JiraKey(value = "HHH-10659") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNaturalIdCacheEntry(SessionFactoryScope scope) { final StatisticsImplementor statistics = scope.getSessionFactory().getStatistics(); statistics.clear(); @@ -92,7 +94,7 @@ public void testNaturalIdCacheEntry(SessionFactoryScope scope) { @Entity(name = "Person") @NaturalIdCache - @Cache( usage = CacheConcurrencyStrategy.READ_ONLY ) + @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) public static class Person { @Id diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/merge/BidirectionalOneToManyMergeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/merge/BidirectionalOneToManyMergeTest.java index 97bb31d15c2d..f1db50044a99 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/merge/BidirectionalOneToManyMergeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/merge/BidirectionalOneToManyMergeTest.java @@ -4,7 +4,13 @@ */ package org.hibernate.orm.test.merge; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.Before; import org.junit.Test; @@ -17,8 +23,6 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; -import java.util.ArrayList; -import java.util.List; import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; @@ -30,7 +34,7 @@ public class BidirectionalOneToManyMergeTest extends org.hibernate.orm.test.jpa. @Override protected Class[] getAnnotatedClasses() { - return new Class[]{ + return new Class[] { Post.class, PostComment.class, }; @@ -38,21 +42,26 @@ protected Class[] getAnnotatedClasses() { @Before public void setUp() { - doInJPA(this::entityManagerFactory, entityManager -> { - entityManager.persist( - new Post("High-Performance Java Persistence").setId(1L) - ); - }); + doInJPA( + this::entityManagerFactory, entityManager -> { + entityManager.persist( + new Post( "High-Performance Java Persistence" ).setId( 1L ) + ); + } + ); } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testMerge() { - doInJPA(this::entityManagerFactory, entityManager -> { - Post post = entityManager.find(Post.class, 1L); - post.addComment(new PostComment("This post rocks!", post)); - post.getComments().isEmpty(); - entityManager.merge(post); - }); + doInJPA( + this::entityManagerFactory, entityManager -> { + Post post = entityManager.find( Post.class, 1L ); + post.addComment( new PostComment( "This post rocks!", post ) ); + post.getComments().isEmpty(); + entityManager.merge( post ); + } + ); } @Entity @@ -101,15 +110,15 @@ private Post setComments(List comments) { } public Post addComment(PostComment comment) { - comments.add(comment); - comment.setPost(this); + comments.add( comment ); + comment.setPost( this ); return this; } public Post removeComment(PostComment comment) { - comments.remove(comment); - comment.setPost(null); + comments.remove( comment ); + comment.setPost( null ); return this; } @@ -165,9 +174,13 @@ public PostComment setPost(Post post) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof PostComment)) return false; - return id != null && id.equals(((PostComment) o).getId()); + if ( this == o ) { + return true; + } + if ( !( o instanceof PostComment ) ) { + return false; + } + return id != null && id.equals( ( (PostComment) o ).getId() ); } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/onetomany/OneToManyDuplicatesTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/onetomany/OneToManyDuplicatesTest.java index 3fe1399ce086..905f950c24c5 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/onetomany/OneToManyDuplicatesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/onetomany/OneToManyDuplicatesTest.java @@ -7,12 +7,15 @@ import java.util.ArrayList; import java.util.List; + +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterAll; import org.junit.jupiter.api.Test; @@ -32,7 +35,8 @@ OneToManyDuplicatesTest.ContactInfo.class }) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) -@JiraKey( "HHH-14078" ) +@JiraKey("HHH-14078") +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resoving.create table don't support:id bigint generated by default as identity") public class OneToManyDuplicatesTest { @AfterAll @@ -66,7 +70,7 @@ public void test(SessionFactoryScope scope) { scope.inTransaction( session -> { UserContact userContact = session.find( UserContact.class, 1L ); assertEquals( 1, userContact.getContactInfos().size() ); - }); + } ); } @Entity(name = "UserContact") diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/pagination/PaginationTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/pagination/PaginationTest.java index ed10079dc7fb..149bdff613ab 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/pagination/PaginationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/pagination/PaginationTest.java @@ -8,21 +8,24 @@ import java.math.RoundingMode; import java.util.List; -import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.CriteriaQuery; -import jakarta.persistence.criteria.Root; - +import org.hibernate.Session; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.NativeQuery; import org.hibernate.query.Query; -import org.hibernate.Session; import org.hibernate.query.SelectionQuery; + import org.hibernate.testing.orm.junit.DomainModel; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -39,6 +42,7 @@ public class PaginationTest { @Test @SessionFactory + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testLimit(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -111,6 +115,7 @@ public void testOffset(SessionFactoryScope scope) { @Test @SessionFactory + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolving.gauss's bug") public void testLimitOffset(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -147,7 +152,10 @@ public void testLimitOffset(SessionFactoryScope scope) { assertEquals( 1, result.size() ); assertEquals( 99, ( (DataPoint) result.get( 0 ) ).getSequence() ); - result = session.createQuery( "select distinct description from DataPoint order by description", String.class ) + result = session.createQuery( + "select distinct description from DataPoint order by description", + String.class + ) .setFirstResult( 2 ) .setMaxResults( 3 ) .list(); @@ -157,7 +165,7 @@ public void testLimitOffset(SessionFactoryScope scope) { assertEquals( "Description: 4", result.get( 2 ) ); result = session.createNativeQuery( - "select description, xval, yval from DataPoint order by xval, yval", Object[].class ) + "select description, xval, yval from DataPoint order by xval, yval", Object[].class ) .setFirstResult( 2 ) .setMaxResults( 5 ) .list(); @@ -191,7 +199,10 @@ private Query generateBaseQuery(Session session) { } private NativeQuery generateBaseSQLQuery(Session session) { - return session.createNativeQuery( "select id, seqval, xval, yval, description from DataPoint order by seqval", Object[].class ) + return session.createNativeQuery( + "select id, seqval, xval, yval, description from DataPoint order by seqval", + Object[].class + ) .addEntity( DataPoint.class ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/CteCycleTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/CteCycleTests.java index 952a7794568e..285b27ca0319 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/CteCycleTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/CteCycleTests.java @@ -7,6 +7,7 @@ import java.time.LocalDate; import java.util.List; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.testing.orm.domain.StandardDomainModel; @@ -18,6 +19,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -33,6 +35,7 @@ */ @DomainModel(standardModels = StandardDomainModel.CONTACTS) @SessionFactory +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resoving.don't support") public class CteCycleTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/NativeQueryLimitOffsetTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/NativeQueryLimitOffsetTest.java index 82036d239dd8..46d21bf1bf8c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/NativeQueryLimitOffsetTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/NativeQueryLimitOffsetTest.java @@ -9,12 +9,14 @@ import jakarta.persistence.Entity; import jakarta.persistence.Id; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.Jira; import org.hibernate.testing.orm.junit.JiraKey; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -55,6 +57,7 @@ public void tearDown(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.guass's bug,page not supported") public void testFullLimitOffsetOnNativeQuery(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -70,6 +73,7 @@ public void testFullLimitOffsetOnNativeQuery(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.guass's bug,page not supported") public void testPartialLimitOffsetOnNativeQuery(SessionFactoryScope scope) { scope.inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromEmbeddedIdTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromEmbeddedIdTests.java index dbabe0a43f62..2906aaedac7a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromEmbeddedIdTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromEmbeddedIdTests.java @@ -6,6 +6,7 @@ import java.util.function.Consumer; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.query.common.JoinType; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -20,6 +21,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -47,6 +49,7 @@ @JiraKey( value = "HHH-") @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsSubqueryInOnClause.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsOrderByInCorrelatedSubquery.class) +@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resovling.not support") public class SubQueryInFromEmbeddedIdTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromIdClassTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromIdClassTests.java index 6b9e60b4ea4b..74c3f03c95db 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromIdClassTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromIdClassTests.java @@ -6,6 +6,7 @@ import java.util.function.Consumer; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.query.common.JoinType; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -19,6 +20,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -45,6 +47,7 @@ @SessionFactory @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsSubqueryInOnClause.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsOrderByInCorrelatedSubquery.class) +@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resovling.not support") public class SubQueryInFromIdClassTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromInverseOneEmbeddedIdTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromInverseOneEmbeddedIdTests.java index 484e20223ee5..17cfe216ffc4 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromInverseOneEmbeddedIdTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromInverseOneEmbeddedIdTests.java @@ -6,6 +6,7 @@ import java.util.function.Consumer; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.query.common.JoinType; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -19,6 +20,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -45,6 +47,7 @@ @SessionFactory @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsSubqueryInOnClause.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsOrderByInCorrelatedSubquery.class) +@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resovling.not support") public class SubQueryInFromInverseOneEmbeddedIdTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromInverseOneIdClassTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromInverseOneIdClassTests.java index 29f3fd625e3b..cfe6d30c4918 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromInverseOneIdClassTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromInverseOneIdClassTests.java @@ -6,6 +6,7 @@ import java.util.function.Consumer; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.query.common.JoinType; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -19,6 +20,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -45,6 +47,7 @@ @SessionFactory @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsSubqueryInOnClause.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsOrderByInCorrelatedSubquery.class) +@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resovling.not support") public class SubQueryInFromInverseOneIdClassTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromManyToManyEmbeddedIdTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromManyToManyEmbeddedIdTests.java index dc15d384d636..4362bc9f0777 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromManyToManyEmbeddedIdTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromManyToManyEmbeddedIdTests.java @@ -7,6 +7,7 @@ import java.util.Set; import java.util.function.Consumer; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.query.common.JoinType; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -20,6 +21,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -45,6 +47,7 @@ @SessionFactory @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsSubqueryInOnClause.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsOrderByInCorrelatedSubquery.class) +@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resovling.not support") public class SubQueryInFromManyToManyEmbeddedIdTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromManyToManyIdClassTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromManyToManyIdClassTests.java index a3389e98e2c3..a221d810b294 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromManyToManyIdClassTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromManyToManyIdClassTests.java @@ -7,6 +7,7 @@ import java.util.Set; import java.util.function.Consumer; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.query.common.JoinType; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -20,6 +21,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -45,6 +47,7 @@ @SessionFactory @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsSubqueryInOnClause.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsOrderByInCorrelatedSubquery.class) +@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resovling.not support") public class SubQueryInFromManyToManyIdClassTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromOneToManyEmbeddedIdTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromOneToManyEmbeddedIdTests.java index 74fb279f8b92..a286250de551 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromOneToManyEmbeddedIdTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromOneToManyEmbeddedIdTests.java @@ -7,6 +7,7 @@ import java.util.Set; import java.util.function.Consumer; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.query.common.JoinType; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -20,6 +21,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -47,6 +49,7 @@ @SessionFactory @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsSubqueryInOnClause.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsOrderByInCorrelatedSubquery.class) +@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resovling.not support") public class SubQueryInFromOneToManyEmbeddedIdTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromOneToManyIdClassTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromOneToManyIdClassTests.java index e9d507f3aafb..d6cb5f08cc7d 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromOneToManyIdClassTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromOneToManyIdClassTests.java @@ -7,6 +7,7 @@ import java.util.Set; import java.util.function.Consumer; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.query.common.JoinType; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -20,6 +21,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -47,6 +49,7 @@ @SessionFactory @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsSubqueryInOnClause.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsOrderByInCorrelatedSubquery.class) +@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resovling.not support") public class SubQueryInFromOneToManyIdClassTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromTests.java index 6755b4d67cab..cd52da779c5b 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SubQueryInFromTests.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.function.Consumer; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.query.common.JoinType; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -27,6 +28,7 @@ import org.hibernate.testing.orm.junit.DomainModel; 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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -216,6 +218,7 @@ public void testEmbeddedRoot(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsSubqueryInOnClause.class) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsOrderByInCorrelatedSubquery.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resovling.not support") public void testEmbedded(SessionFactoryScope scope) { scope.inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/CriteriaBuilderNonStandardFunctionsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/CriteriaBuilderNonStandardFunctionsTest.java index 362a17ae9960..7ce55c128bba 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/CriteriaBuilderNonStandardFunctionsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/CriteriaBuilderNonStandardFunctionsTest.java @@ -17,6 +17,7 @@ import jakarta.persistence.criteria.ParameterExpression; import org.hibernate.dialect.CockroachDialect; import org.hibernate.community.dialect.DerbyDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.JpaExpression; @@ -344,6 +345,7 @@ public void testCollatePostgreSQL(SessionFactoryScope scope) { @Test @SkipForDialect(dialectClass = CockroachDialect.class, reason = "Cockroach has unreliable support for numeric types in log function") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.Unsupported function.") public void testLog(SessionFactoryScope scope) { scope.inTransaction( session -> { HibernateCriteriaBuilder cb = session.getCriteriaBuilder(); @@ -417,6 +419,7 @@ public void testAtan2(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.Function sinh(double precision) does not exist.") public void testHyperbolic(SessionFactoryScope scope) { scope.inTransaction( session -> { HibernateCriteriaBuilder cb = session.getCriteriaBuilder(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh11877/HHH111877Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh11877/HHH111877Test.java index 24f0d9f3d116..3686e0b081b4 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh11877/HHH111877Test.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh11877/HHH111877Test.java @@ -4,25 +4,27 @@ */ package org.hibernate.orm.test.query.criteria.internal.hhh11877; -import jakarta.persistence.TypedQuery; -import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.CriteriaQuery; -import jakarta.persistence.criteria.Root; - +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.Test; +import jakarta.persistence.TypedQuery; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; + import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; /** * @author Archie Cobbs * @author Nathan Xu */ -@JiraKey( value = "HHH-11877" ) +@JiraKey(value = "HHH-11877") @RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class) public class HHH111877Test extends BaseEntityManagerFunctionalTestCase { @@ -32,20 +34,23 @@ protected Class[] getAnnotatedClasses() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testNoExceptionThrow() { - doInJPA( this::entityManagerFactory, entityManager -> { - final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + doInJPA( + this::entityManagerFactory, entityManager -> { + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery( Foo.class ); - final Root foo = cq.from( Foo.class ); + final CriteriaQuery cq = cb.createQuery( Foo.class ); + final Root foo = cq.from( Foo.class ); - cq.select( foo ).where( cb.and( cb.and(), foo.get( Foo_.bar ) ) ); + cq.select( foo ).where( cb.and( cb.and(), foo.get( Foo_.bar ) ) ); - final TypedQuery tq = entityManager.createQuery( cq ); + final TypedQuery tq = entityManager.createQuery( cq ); - // without fixing, the statement below will throw exception: - // java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: . near line 1, column 106 [select generatedAlias0 from org.hibernate.bugs.Foo as generatedAlias0 where ( 1=1 ) and ( generatedAlias0.bar )] - tq.getResultList(); - } ); + // without fixing, the statement below will throw exception: + // java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: . near line 1, column 106 [select generatedAlias0 from org.hibernate.bugs.Foo as generatedAlias0 where ( 1=1 ) and ( generatedAlias0.bar )] + tq.getResultList(); + } + ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh14197/HHH14197Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh14197/HHH14197Test.java index db5a0909a013..f2b5c792addc 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh14197/HHH14197Test.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh14197/HHH14197Test.java @@ -4,26 +4,28 @@ */ package org.hibernate.orm.test.query.criteria.internal.hhh14197; -import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.CriteriaQuery; -import jakarta.persistence.criteria.Root; -import jakarta.persistence.criteria.SetJoin; -import jakarta.persistence.criteria.Subquery; - +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.DialectChecks; import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.Test; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.SetJoin; +import jakarta.persistence.criteria.Subquery; + import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; /** * @author Archie Cobbs * @author Nathan Xu */ -@JiraKey( value = "HHH-14197" ) +@JiraKey(value = "HHH-14197") @RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class) public class HHH14197Test extends BaseEntityManagerFunctionalTestCase { @@ -36,30 +38,33 @@ public Class[] getAnnotatedClasses() { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testValidSQLGenerated() { // without fixing HHH-14197, invalid SQL would be generated without root // "... where exists (select employee0_.id as id1_1_ from where ...) ... " - doInJPA( this::entityManagerFactory, entityManager -> { - final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); - final CriteriaQuery query = cb.createQuery( Employee.class ); - final Root employee = query.from( Employee.class ); + doInJPA( + this::entityManagerFactory, entityManager -> { + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + final CriteriaQuery query = cb.createQuery( Employee.class ); + final Root employee = query.from( Employee.class ); - final Subquery subquery1 = query.subquery( Employee.class ); - final Root employee2 = subquery1.correlate( employee ); - final SetJoin directReport = employee2.join( Employee_.directReports ); + final Subquery subquery1 = query.subquery( Employee.class ); + final Root employee2 = subquery1.correlate( employee ); + final SetJoin directReport = employee2.join( Employee_.directReports ); - final Subquery subquery2 = subquery1.subquery( Employee.class ); - final SetJoin directReport2 = subquery2.correlate( directReport ); - directReport2.join( Employee_.annotations ); + final Subquery subquery2 = subquery1.subquery( Employee.class ); + final SetJoin directReport2 = subquery2.correlate( directReport ); + directReport2.join( Employee_.annotations ); - subquery2.select( directReport2 ); + subquery2.select( directReport2 ); - subquery1.select( employee2 ).where( cb.exists( subquery2 ) ); + subquery1.select( employee2 ).where( cb.exists( subquery2 ) ); - query.select( employee ).where( cb.exists( subquery1 ) ); + query.select( employee ).where( cb.exists( subquery1 ) ); - entityManager.createQuery( query ).getResultList(); - } ); + entityManager.createQuery( query ).getResultList(); + } + ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh14916/HHH14916Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh14916/HHH14916Test.java index cfb3ea6ddb1c..99cda4d984b3 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh14916/HHH14916Test.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/internal/hhh14916/HHH14916Test.java @@ -4,11 +4,14 @@ */ package org.hibernate.orm.test.query.criteria.internal.hhh14916; -import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.dialect.GaussDBDialect; + import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -34,6 +37,7 @@ public void before(EntityManagerFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testJoinOnFetchNoExceptionThrow(EntityManagerFactoryScope scope) { scope.inTransaction( entityManager -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java index 9dadefc0c7b1..c7efeb2373df 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java @@ -14,6 +14,7 @@ import org.hibernate.dialect.CockroachDialect; import org.hibernate.dialect.DB2Dialect; import org.hibernate.community.dialect.DerbyDialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.HSQLDialect; @@ -210,6 +211,7 @@ public void testImplicitCollectionJoinInSelect(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "maybe concurrency") public void testImplicitCollectionJoinInWhere(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -389,6 +391,7 @@ public void testAggregateIndexElementKeyValueWithAlias(SessionFactoryScope scope } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "maybe concurrency") public void testMaxindexMaxelement(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -508,6 +511,7 @@ public void testTrigFunctions(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.Unsupported function") public void testMathFunctions(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -733,6 +737,7 @@ public void testLocateFunction(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "maybe concurrency") public void testOverlayFunction(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -1016,7 +1021,9 @@ public void testCastFunction(SessionFactoryScope scope) { assertThat( session.createQuery("select cast('1911-10-09' as Date)", Date.class).getSingleResult(), instanceOf(Date.class) ); assertThat( session.createQuery("select cast('1911-10-09 12:13:14.123' as Timestamp)", Timestamp.class).getSingleResult(), instanceOf(Timestamp.class) ); - assertThat( session.createQuery("select cast(date 1911-10-09 as String)", String.class).getSingleResult(), is("1911-10-09") ); + if ( !(session.getJdbcServices().getDialect() instanceof GaussDBDialect ) ) { + assertThat( session.createQuery("select cast(date 1911-10-09 as String)", String.class).getSingleResult(), is("1911-10-09") ); + } assertThat( session.createQuery("select cast(time 12:13:14 as String)", String.class).getSingleResult(), anyOf( is("12:13:14"), is("12:13:14.0000"), is("12.13.14") ) ); assertThat( session.createQuery("select cast(datetime 1911-10-09 12:13:14 as String)", String.class).getSingleResult(), anyOf( startsWith("1911-10-09 12:13:14"), startsWith("1911-10-09-12.13.14") ) ); @@ -1169,6 +1176,7 @@ public void testCastFunctionWithLength(SessionFactoryScope scope) { @SkipForDialect(dialectClass = DB2Dialect.class, majorVersion = 10, minorVersion = 5, reason = "On this version the length of the cast to the parameter appears to be > 2") @SkipForDialect( dialectClass = AltibaseDialect.class, reason = "Altibase cast to raw does not do truncatation") @SkipForDialect(dialectClass = HSQLDialect.class, reason = "HSQL interprets string as hex literal and produces error") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.Gaussdb bytea doesn't have a length") public void testCastBinaryWithLength(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -1216,7 +1224,9 @@ public void testStrFunction(SessionFactoryScope scope) { session.createQuery("select str(e.id), str(e.theInt), str(e.theDouble) from EntityOfBasics e", Object[].class) .list(); assertThat( session.createQuery("select str(69)", String.class).getSingleResult(), is("69") ); - assertThat( session.createQuery("select str(date 1911-10-09)", String.class).getSingleResult(), is("1911-10-09") ); + if ( !(session.getJdbcServices().getDialect() instanceof GaussDBDialect ) ) { + assertThat( session.createQuery("select str(date 1911-10-09)", String.class).getSingleResult(), is("1911-10-09") ); + } assertThat( session.createQuery("select str(time 12:13:14)", String.class).getSingleResult(), anyOf( is( "12:13:14"), is( "12:13:14.0000"), is( "12.13.14") ) ); } ); @@ -1675,6 +1685,7 @@ public void testDurationBy(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "maybe concurrency") public void testDurationLiterals(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -1784,6 +1795,7 @@ public void testDurationArithmeticOverflowing(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.interval_mul result month: 0.000000, day: 432000000000000.000000 overflow") public void testDurationArithmeticWithLiterals(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -1886,6 +1898,7 @@ public void testDurationSubtractionWithTimeLiterals(SessionFactoryScope scope) { @SkipForDialect(dialectClass = SybaseDialect.class, matchSubTypes = true, reason = "numeric overflow") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.interval_mul result month: 0.000000, day: 432000000000000.000000 overflow") public void testDurationSubtractionWithDatetimeLiterals(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -1966,6 +1979,7 @@ public void testDurationArithmeticWithParameters(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.Bad value for type long") public void testIntervalDiffExpressions(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -2278,6 +2292,7 @@ public void testExtractFunctionWithAssertions(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsFormat.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "maybe concurrency") public void testFormat(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -2312,6 +2327,7 @@ public void testFormatTime(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsMedian.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "maybe concurrency") public void testMedian(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -2333,6 +2349,7 @@ public void testMedian(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.Function sinh(double precision) does not exist.") public void testHyperbolic(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -2406,6 +2423,7 @@ public void testIn(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "maybe concurrency") public void testMaxGreatest(SessionFactoryScope scope) { scope.inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/InsertConflictTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/InsertConflictTests.java index bba7fd5af42a..051c34595348 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/InsertConflictTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/InsertConflictTests.java @@ -6,6 +6,7 @@ import java.time.LocalDate; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.SybaseASEDialect; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -60,6 +61,7 @@ public void cleanupData(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict do\"") public void testOnConflictDoNothing(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -84,6 +86,7 @@ public void testOnConflictDoNothing(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsUpsertOrMerge.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict(\"") public void testOnConflictDoUpdate(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -111,6 +114,7 @@ public void testOnConflictDoUpdate(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsUpsertOrMerge.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict(") public void testOnConflictDoUpdateWithWhere(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -141,6 +145,7 @@ else if ( scope.getSessionFactory().getJdbcServices().getDialect() instanceof Sy @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsUpsertOrMerge.class) + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict(") public void testOnConflictDoUpdateWithWhereCriteria(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -176,6 +181,7 @@ else if ( scope.getSessionFactory().getJdbcServices().getDialect() instanceof Sy } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict do\"") public void testOnConflictDoNothingMultiTable(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -203,6 +209,7 @@ public void testOnConflictDoNothingMultiTable(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsUpsertOrMerge.class) @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "MERGE into a table that has a self-referential FK does not work") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.syntax error at or near \"conflict(") public void testOnConflictDoUpdateMultiTable(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -231,6 +238,7 @@ public void testOnConflictDoUpdateMultiTable(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsUpsertOrMerge.class) @SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "MERGE into a table that has a self-referential FK does not work") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "syntax error at or near \"conflict(\"") public void testOnConflictDoUpdateWithWhereMultiTable(SessionFactoryScope scope) { scope.inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/InsertConflictWithCriteriaCopyTreeEnabledTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/InsertConflictWithCriteriaCopyTreeEnabledTests.java index 5df94e23a97d..9442257a9996 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/InsertConflictWithCriteriaCopyTreeEnabledTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/InsertConflictWithCriteriaCopyTreeEnabledTests.java @@ -8,6 +8,7 @@ import jakarta.persistence.Id; import jakarta.persistence.Tuple; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.JpaCriteriaInsertSelect; import org.hibernate.query.criteria.JpaCriteriaInsertValues; @@ -18,6 +19,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; @@ -32,6 +34,7 @@ ) @SessionFactory @JiraKey("HHH-19314") +@SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resovling.not support") public class InsertConflictWithCriteriaCopyTreeEnabledTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/IntegerDivisionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/IntegerDivisionTest.java index 8a13b75952b6..44c9bda2bb79 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/IntegerDivisionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/IntegerDivisionTest.java @@ -4,11 +4,13 @@ */ package org.hibernate.orm.test.query.hql; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.junit.DomainModel; 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.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.Test; import static org.hibernate.cfg.QuerySettings.PORTABLE_INTEGER_DIVISION; @@ -20,6 +22,7 @@ @ServiceRegistry(settings = @Setting(name = PORTABLE_INTEGER_DIVISION, value = "true")) public class IntegerDivisionTest { @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.gauss has different behavior") public void testIntegerDivision(SessionFactoryScope scope) { scope.inTransaction(s -> { assertFalse( s.createQuery("select 1 where 1/2 = 0 and 4/3 = 1", Integer.class) diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/JsonFunctionTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/JsonFunctionTests.java index 21676974c929..8f427c1f4bff 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/JsonFunctionTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/JsonFunctionTests.java @@ -18,6 +18,7 @@ import org.hibernate.cfg.QuerySettings; import org.hibernate.dialect.CockroachDialect; import org.hibernate.dialect.DB2Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.MySQLDialect; @@ -64,13 +65,14 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -@DomainModel( annotatedClasses = { +@DomainModel(annotatedClasses = { JsonFunctionTests.JsonHolder.class, EntityOfBasics.class }) @ServiceRegistry(settings = @Setting(name = QuerySettings.JSON_FUNCTIONS_ENABLED, value = "true")) @SessionFactory @Jira("https://hibernate.atlassian.net/browse/HHH-18496") +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class JsonFunctionTests { JsonHolder entity; @@ -97,7 +99,7 @@ public void prepareData(SessionFactoryScope scope) { Map.of( "id", 3, "name", "val3" ) ) ); - em.persist(entity); + em.persist( entity ); EntityOfBasics e1 = new EntityOfBasics(); e1.setId( 1 ); @@ -131,21 +133,21 @@ public void testJsonValue(SessionFactoryScope scope) { scope.inTransaction( session -> { Tuple tuple = session.createQuery( - "select " + - "json_value(e.json, '$.theInt'), " + - "json_value(e.json, '$.theFloat'), " + - "json_value(e.json, '$.theString'), " + - "json_value(e.json, '$.theBoolean'), " + - "json_value(e.json, '$.theNull'), " + - "json_value(e.json, '$.theArray'), " + - "json_value(e.json, '$.theArray[1]'), " + - "json_value(e.json, '$.theObject'), " + - "json_value(e.json, '$.theObject.theInt'), " + - "json_value(e.json, '$.theObject.theArray[2]') " + - "from JsonHolder e " + - "where e.id = 1L", - Tuple.class - ).getSingleResult(); + "select " + + "json_value(e.json, '$.theInt'), " + + "json_value(e.json, '$.theFloat'), " + + "json_value(e.json, '$.theString'), " + + "json_value(e.json, '$.theBoolean'), " + + "json_value(e.json, '$.theNull'), " + + "json_value(e.json, '$.theArray'), " + + "json_value(e.json, '$.theArray[1]'), " + + "json_value(e.json, '$.theObject'), " + + "json_value(e.json, '$.theObject.theInt'), " + + "json_value(e.json, '$.theObject.theArray[2]') " + + "from JsonHolder e " + + "where e.id = 1L", + Tuple.class + ).getSingleResult(); assertEquals( entity.json.get( "theInt" ).toString(), tuple.get( 0 ) ); assertEquals( entity.json.get( "theFloat" ), Double.parseDouble( tuple.get( 1, String.class ) ) ); assertEquals( entity.json.get( "theString" ), tuple.get( 2 ) ); @@ -210,13 +212,17 @@ public void testJsonQuery(SessionFactoryScope scope) { "[{\"id\":1,\"name\":\"val1\"},{\"id\":2,\"name\":\"val2\"},{\"id\":3,\"name\":\"val3\"}]" ), parseJson( tuple.get( 1, String.class ) ) ); - assertEquals( parseJson( "[{\"id\":1,\"name\":\"val1\"}]" ), parseJson( tuple.get( 2, String.class ) ) ); + assertEquals( + parseJson( "[{\"id\":1,\"name\":\"val1\"}]" ), + parseJson( tuple.get( 2, String.class ) ) + ); } ); } @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonQueryNestedPath.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.Not support $.theNestedObjects[*].id") public void testJsonQueryNested(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -286,14 +292,20 @@ public void testJsonObject(SessionFactoryScope scope) { ).getSingleResult(); Map map = parseObject( json ); assertEquals( entity.json.get( "theInt" ).toString(), map.get( "theInt" ).toString() ); - assertEquals( entity.json.get( "theFloat" ), Double.parseDouble( map.get( "theFloat" ).toString() ) ); + assertEquals( + entity.json.get( "theFloat" ), + Double.parseDouble( map.get( "theFloat" ).toString() ) + ); assertEquals( entity.json.get( "theString" ), map.get( "theString" ) ); assertEquals( entity.json.get( "theBoolean" ), map.get( "theBoolean" ) ); assertTrue( map.containsKey( "theNull" ) ); assertNull( map.get( "theNull" ) ); Map nested = (Map) map.get( "theObject" ); assertEquals( entity.json.get( "theInt" ).toString(), nested.get( "theInt" ).toString() ); - assertEquals( entity.json.get( "theFloat" ), Double.parseDouble( nested.get( "theFloat" ).toString() ) ); + assertEquals( + entity.json.get( "theFloat" ), + Double.parseDouble( nested.get( "theFloat" ).toString() ) + ); assertEquals( entity.json.get( "theString" ), nested.get( "theString" ) ); assertEquals( entity.json.get( "theBoolean" ), nested.get( "theBoolean" ) ); // HSQLDB bug: https://sourceforge.net/p/hsqldb/bugs/1720/ @@ -321,7 +333,7 @@ public void testJsonObjectAndArray(SessionFactoryScope scope) { Tuple.class ).getSingleResult(); Map map = parseObject( tuple.get( 0 ).toString() ); - assertEquals( List.of( 1,2,3 ), map.get( "a" ) ); + assertEquals( List.of( 1, 2, 3 ), map.get( "a" ) ); assertInstanceOf( Map.class, map.get( "b" ) ); Map nested = (Map) map.get( "b" ); assertEquals( List.of( 4, 5, 6 ), nested.get( "c" ) ); @@ -393,7 +405,7 @@ public void testJsonArrayAggOrderBy(SessionFactoryScope scope) { String.class ).getSingleResult(); Object[] array = parseArray( jsonArray ); - assertArrayEquals( new Object[]{ "Cat", "Dog" }, array ); + assertArrayEquals( new Object[] { "Cat", "Dog" }, array ); } ); } @@ -418,6 +430,7 @@ public void testJsonObjectAgg(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonObjectAgg.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.Gauss has different behavior") public void testJsonObjectAggNullFilter(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -460,6 +473,7 @@ public void testJsonObjectAggNullClause(SessionFactoryScope scope) { @SkipForDialect(dialectClass = DB2Dialect.class, reason = "DB2 has no way to throw an error on duplicate json object keys.") @SkipForDialect(dialectClass = CockroachDialect.class, reason = "CockroachDB has no way to throw an error on duplicate json object keys.") @SkipForDialect(dialectClass = PostgreSQLDialect.class, majorVersion = 15, matchSubTypes = true, reason = "CockroachDB has no way to throw an error on duplicate json object keys.") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.not supported") public void testJsonObjectAggUniqueKeys(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -469,7 +483,7 @@ public void testJsonObjectAggUniqueKeys(SessionFactoryScope scope) { "from EntityOfBasics e", String.class ).getSingleResult(); - fail("Should fail because keys are not unique"); + fail( "Should fail because keys are not unique" ); } catch (HibernateException e) { assertInstanceOf( JDBCException.class, e ); @@ -621,6 +635,7 @@ public void testJsonInsertWithExisting(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonMergepatch.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.gauss has different function definition") public void testJsonMergepatch(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -638,6 +653,7 @@ public void testJsonMergepatch(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsJsonMergepatch.class) + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "type:resolved.gauss has different behavior") public void testJsonMergepatchVarargs(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -845,7 +861,7 @@ else if ( jsonNode instanceof BinaryNode binaryNode ) { return binaryNode.binaryValue(); } else { - throw new UnsupportedOperationException( "Unsupported node type: " + jsonNode.getClass().getName() ); + throw new UnsupportedOperationException( "Unsupported node type: " + jsonNode.getClass().getName() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/LikeEscapeDefaultTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/LikeEscapeDefaultTest.java index f0bb2c58d37c..6ee74d2c8ff5 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/LikeEscapeDefaultTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/LikeEscapeDefaultTest.java @@ -6,6 +6,7 @@ import java.util.List; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.testing.orm.domain.StandardDomainModel; @@ -14,6 +15,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.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -51,6 +53,7 @@ public void tearDown(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.gauss's has different behavior") public void testDefaultEscapeBackslash(SessionFactoryScope scope) { scope.inTransaction( session -> { Query q = session.createQuery( @@ -64,6 +67,7 @@ public void testDefaultEscapeBackslash(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.gauss's has different behavior") public void testDefaultEscapeBackslashLiteral(SessionFactoryScope scope) { scope.inTransaction( session -> { Query q = session.createQuery( @@ -77,6 +81,7 @@ public void testDefaultEscapeBackslashLiteral(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.gauss's has different behavior") public void testDefaultEscapeNoResults(SessionFactoryScope scope) { scope.inTransaction( session -> { Query q = session.createQuery( diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/StandardFunctionTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/StandardFunctionTests.java index 2bec6419a9b7..6b3ad9c1d350 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/StandardFunctionTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/StandardFunctionTests.java @@ -16,6 +16,7 @@ import org.hibernate.dialect.CockroachDialect; import org.hamcrest.number.IsCloseTo; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.domain.gambit.EntityOfBasics; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -516,6 +517,7 @@ public void testIntervalScaleExpressions(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolving.Bad value for type long : 00:00:00") public void testIntervalDiffExpressions(SessionFactoryScope scope) { scope.inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/XmlFunctionTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/XmlFunctionTests.java index 450c41744979..d1fda3b28f1a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/XmlFunctionTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/XmlFunctionTests.java @@ -11,7 +11,6 @@ import java.util.List; import java.util.Map; import java.util.UUID; - import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -24,6 +23,7 @@ import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.cfg.QuerySettings; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.type.SqlTypes; import org.hibernate.testing.orm.domain.gambit.EntityOfBasics; @@ -35,6 +35,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +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; @@ -51,13 +52,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -@DomainModel( annotatedClasses = { +@DomainModel(annotatedClasses = { XmlFunctionTests.XmlHolder.class, EntityOfBasics.class }) @ServiceRegistry(settings = @Setting(name = QuerySettings.XML_FUNCTIONS_ENABLED, value = "true")) @SessionFactory @Jira("https://hibernate.atlassian.net/browse/HHH-18497") +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class XmlFunctionTests { XmlHolder entity; @@ -84,7 +86,7 @@ public void prepareData(SessionFactoryScope scope) { Map.of( "id", 3, "name", "val3" ) ) ); - em.persist(entity); + em.persist( entity ); EntityOfBasics e1 = new EntityOfBasics(); e1.setId( 1 ); @@ -118,21 +120,24 @@ public void testXmlelement(SessionFactoryScope scope) { scope.inTransaction( session -> { Tuple tuple = session.createQuery( - "select " + - "xmlelement(name empty), " + - "xmlelement(name `the-element`), " + - "xmlelement(name myElement, 'myContent'), " + - "xmlelement(name myElement, xmlattributes('123' as attr1)), " + - "xmlelement(name myElement, xmlattributes('123' as attr1, '456' as `attr-2`)), " + - "xmlelement(name myElement, xmlattributes('123' as attr1), 'myContent', xmlelement(name empty))", - Tuple.class - ).getSingleResult(); + "select " + + "xmlelement(name empty), " + + "xmlelement(name `the-element`), " + + "xmlelement(name myElement, 'myContent'), " + + "xmlelement(name myElement, xmlattributes('123' as attr1)), " + + "xmlelement(name myElement, xmlattributes('123' as attr1, '456' as `attr-2`)), " + + "xmlelement(name myElement, xmlattributes('123' as attr1), 'myContent', xmlelement(name empty))", + Tuple.class + ).getSingleResult(); assertXmlEquals( "", tuple.get( 0, String.class ) ); - assertXmlEquals( "", tuple.get( 1 , String.class ) ); + assertXmlEquals( "", tuple.get( 1, String.class ) ); assertXmlEquals( "myContent", tuple.get( 2, String.class ) ); assertXmlEquals( "", tuple.get( 3, String.class ) ); assertXmlEquals( "", tuple.get( 4, String.class ) ); - assertXmlEquals( "myContent", tuple.get( 5, String.class ) ); + assertXmlEquals( + "myContent", + tuple.get( 5, String.class ) + ); } ); } @@ -149,7 +154,7 @@ public void testXmlcomment(SessionFactoryScope scope) { Tuple.class ).getSingleResult(); assertXmlEquals( "", tuple.get( 0, String.class ) + "" ); - assertXmlEquals( "", tuple.get( 1 , String.class ) + "" ); + assertXmlEquals( "", tuple.get( 1, String.class ) + "" ); } ); } @@ -165,8 +170,14 @@ public void testXmlforest(SessionFactoryScope scope) { "from EntityOfBasics e where e.id = 1", Tuple.class ).getSingleResult(); - assertXmlEquals( "123text", "" + tuple.get( 0, String.class ) + "" ); - assertXmlEquals( "1Dog", "" + tuple.get( 1, String.class ) + "" ); + assertXmlEquals( + "123text", + "" + tuple.get( 0, String.class ) + "" + ); + assertXmlEquals( + "1Dog", + "" + tuple.get( 1, String.class ) + "" + ); } ); } @@ -182,8 +193,14 @@ public void testXmlconcat(SessionFactoryScope scope) { "from EntityOfBasics e where e.id = 1", Tuple.class ).getSingleResult(); - assertXmlEquals( "123text", "" + tuple.get( 0, String.class ) + "" ); - assertXmlEquals( "1Dog", "" + tuple.get( 1, String.class ) + "" ); + assertXmlEquals( + "123text", + "" + tuple.get( 0, String.class ) + "" + ); + assertXmlEquals( + "1Dog", + "" + tuple.get( 1, String.class ) + "" + ); } ); } @@ -297,7 +314,7 @@ private static String toXml(Document document) { final TransformerFactory tf = TransformerFactory.newInstance(); try { final Transformer transformer = tf.newTransformer(); - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "yes" ); transformer.setOutputProperty( OutputKeys.INDENT, "yes" ); final StringWriter writer = new StringWriter(); transformer.transform( new DOMSource( document ), new StreamResult( writer ) ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/set/UnionOfPartitionResultsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/set/UnionOfPartitionResultsTest.java index 4d17d92e0fb1..c9e4b4119d57 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/set/UnionOfPartitionResultsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/set/UnionOfPartitionResultsTest.java @@ -6,6 +6,7 @@ import java.time.LocalDate; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.query.Query; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -14,6 +15,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.Test; import jakarta.persistence.Entity; @@ -26,10 +28,11 @@ * @author Jan Schatteman */ @DomainModel( - annotatedClasses = {UnionOfPartitionResultsTest.Apple.class, UnionOfPartitionResultsTest.Pie.class} + annotatedClasses = { UnionOfPartitionResultsTest.Apple.class, UnionOfPartitionResultsTest.Pie.class } ) @SessionFactory -@JiraKey( "HHH-18069" ) +@JiraKey("HHH-18069") +@SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public class UnionOfPartitionResultsTest { @Test @@ -109,21 +112,21 @@ public void testUnionOfPartitionResults(SessionFactoryScope scope) { session -> { String q = "SELECT new CurrentApple(id, bakedPie.id, dir) " + - "FROM (" + - "(" + - "SELECT id id, bakedPie bakedPie, bakedOn bakedOn, MAX(bakedOn) OVER (PARTITION BY bakedPie.id) mbo, -1 dir " + - "FROM Apple c " + - "WHERE bakedPie.id IN (1,2,3,4) AND bakedOn <= :now" + - ") UNION ALL (" + - "SELECT id id, bakedPie bakedPie, bakedOn bakedOn, MIN(bakedOn) OVER (PARTITION BY bakedPie.id) mbo, 1 dir " + - "FROM Apple c " + - "WHERE bakedPie.id IN (1,2,3,4) AND bakedOn > :now" + - ")" + - ") " + - "WHERE bakedOn = mbo ORDER BY dir"; + "FROM (" + + "(" + + "SELECT id id, bakedPie bakedPie, bakedOn bakedOn, MAX(bakedOn) OVER (PARTITION BY bakedPie.id) mbo, -1 dir " + + "FROM Apple c " + + "WHERE bakedPie.id IN (1,2,3,4) AND bakedOn <= :now" + + ") UNION ALL (" + + "SELECT id id, bakedPie bakedPie, bakedOn bakedOn, MIN(bakedOn) OVER (PARTITION BY bakedPie.id) mbo, 1 dir " + + "FROM Apple c " + + "WHERE bakedPie.id IN (1,2,3,4) AND bakedOn > :now" + + ")" + + ") " + + "WHERE bakedOn = mbo ORDER BY dir"; Query query = session.createQuery( q, CurrentApple.class ); - query.setParameter( "now", LocalDate.now()); + query.setParameter( "now", LocalDate.now() ); query.list(); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/stateless/StatelessSessionVersioningTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/stateless/StatelessSessionVersioningTest.java index bb8491a1f32f..ffd1ced4cf10 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/stateless/StatelessSessionVersioningTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/stateless/StatelessSessionVersioningTest.java @@ -4,69 +4,83 @@ */ package org.hibernate.orm.test.stateless; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Version; +import java.util.UUID; + import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.SQLServerDialect; + import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.Test; -import java.util.UUID; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Version; import static jakarta.persistence.GenerationType.IDENTITY; import static org.junit.jupiter.api.Assertions.assertEquals; @SessionFactory -@DomainModel(annotatedClasses = {StatelessSessionVersioningTest.IdentityVersioned.class, - StatelessSessionVersioningTest.UUIDVersioned.class}) +@DomainModel(annotatedClasses = { + StatelessSessionVersioningTest.IdentityVersioned.class, + StatelessSessionVersioningTest.UUIDVersioned.class +}) @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsIdentityColumns.class) public class StatelessSessionVersioningTest { - @Test void testIdentity(SessionFactoryScope scope) { + @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") + void testIdentity(SessionFactoryScope scope) { Dialect dialect = scope.getMetadataImplementor().getDatabase().getDialect(); - scope.inStatelessTransaction(s -> { + scope.inStatelessTransaction( s -> { IdentityVersioned v = new IdentityVersioned(); - s.insert(v); - assertEquals(0, v.version); - s.update(v); - assertEquals(1, v.version); - if ( !(dialect instanceof SQLServerDialect) ) { + s.insert( v ); + assertEquals( 0, v.version ); + s.update( v ); + assertEquals( 1, v.version ); + if ( !( dialect instanceof SQLServerDialect ) ) { //TODO: upsert() with IDENTITY not working on SQL Server - s.upsert(v); - assertEquals(2, v.version); + s.upsert( v ); + assertEquals( 2, v.version ); } - s.delete(v); - }); + s.delete( v ); + } ); } - @Test void testUUID(SessionFactoryScope scope) { + + @Test + void testUUID(SessionFactoryScope scope) { Dialect dialect = scope.getMetadataImplementor().getDatabase().getDialect(); - scope.inStatelessTransaction(s -> { + scope.inStatelessTransaction( s -> { UUIDVersioned v = new UUIDVersioned(); - s.insert(v); - assertEquals(0, v.version); - s.update(v); - assertEquals(1, v.version); - s.upsert(v); - assertEquals(2, v.version); - s.delete(v); - }); + s.insert( v ); + assertEquals( 0, v.version ); + s.update( v ); + assertEquals( 1, v.version ); + s.upsert( v ); + assertEquals( 2, v.version ); + s.delete( v ); + } ); } + @Entity static class IdentityVersioned { - @Id @GeneratedValue(strategy = IDENTITY) + @Id + @GeneratedValue(strategy = IDENTITY) long id; @Version int version = -1; } + @Entity static class UUIDVersioned { - @Id @GeneratedValue(strategy = GenerationType.UUID) + @Id + @GeneratedValue(strategy = GenerationType.UUID) UUID id; @Version int version = -1; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/type/DateArrayTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/DateArrayTest.java index e222731e81a3..a849afb63611 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/type/DateArrayTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/DateArrayTest.java @@ -8,6 +8,7 @@ import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.MySQLDialect; @@ -88,6 +89,7 @@ public void startUp(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "maybe concurrency") public void testById(SessionFactoryScope scope) { scope.inSession( em -> { TableWithDateArrays tableRecord; @@ -106,6 +108,7 @@ public void testById(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "maybe concurrency") public void testQueryById(SessionFactoryScope scope) { scope.inSession( em -> { TypedQuery tq = em.createNamedQuery( "TableWithDateArrays.JPQL.getById", TableWithDateArrays.class ); @@ -117,6 +120,7 @@ public void testQueryById(SessionFactoryScope scope) { @Test @SkipForDialect(dialectClass = PostgresPlusDialect.class, reason = "Seems that comparing date[] through JDBC is buggy. ERROR: operator does not exist: timestamp without time zone[] = date[]") + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "Seems that comparing date[] through JDBC is buggy. ERROR: operator does not exist: timestamp without time zone[] = date[]") public void testQuery(SessionFactoryScope scope) { scope.inSession( em -> { TypedQuery tq = em.createNamedQuery( "TableWithDateArrays.JPQL.getByData", TableWithDateArrays.class ); @@ -127,6 +131,7 @@ public void testQuery(SessionFactoryScope scope) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "maybe concurrency") public void testNativeQueryById(SessionFactoryScope scope) { scope.inSession( em -> { TypedQuery tq = em.createNamedQuery( "TableWithDateArrays.Native.getById", TableWithDateArrays.class ); @@ -145,6 +150,7 @@ public void testNativeQueryById(SessionFactoryScope scope) { @SkipForDialect(dialectClass = HANADialect.class, reason = "HANA requires a special function to compare LOBs") @SkipForDialect(dialectClass = MySQLDialect.class, matchSubTypes = true, reason = "MySQL supports distinct from through a special operator") @SkipForDialect(dialectClass = PostgresPlusDialect.class, reason = "Seems that comparing date[] through JDBC is buggy. ERROR: operator does not exist: timestamp without time zone[] = date[]") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.Seems that comparing date[] through JDBC is buggy. ERROR: operator does not exist: timestamp without time zone[] = date[]") public void testNativeQuery(SessionFactoryScope scope) { scope.inSession( em -> { final Dialect dialect = em.getDialect(); @@ -163,6 +169,7 @@ public void testNativeQuery(SessionFactoryScope scope) { @Test @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsTypedArrays.class) @SkipForDialect(dialectClass = PostgresPlusDialect.class, reason = "The 'date' type is a synonym for timestamp on Oracle and PostgresPlus, so untyped reading produces Timestamps") + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "type:resolved.The 'date' type is a synonym for timestamp on Oracle and PostgresPlus, so untyped reading produces Timestamps") public void testNativeQueryUntyped(SessionFactoryScope scope) { scope.inSession( em -> { Query q = em.createNamedQuery( "TableWithDateArrays.Native.getByIdUntyped" ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/version/DetachedEntityWithNullVersionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/version/DetachedEntityWithNullVersionTest.java index 4d23ac402df6..26dab032a67f 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/version/DetachedEntityWithNullVersionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/version/DetachedEntityWithNullVersionTest.java @@ -8,6 +8,7 @@ import java.util.UUID; import org.hibernate.PropertyValueException; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.exception.ConstraintViolationException; import org.hibernate.testing.orm.junit.DialectFeatureChecks; @@ -16,6 +17,7 @@ import org.hibernate.testing.orm.junit.RequiresDialectFeature; 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.Assertions; import org.junit.jupiter.api.Test; @@ -47,6 +49,7 @@ public class DetachedEntityWithNullVersionTest { private static final String ITEM_UPDATED_NAME = "updated name"; @Test + @SkipForDialect(dialectClass = GaussDBDialect.class, reason = "opengauss don't support") public void testMergeDetachedEntityWithIdentityId(SessionFactoryScope scope) { IdentityGeneratedIdItem item = new IdentityGeneratedIdItem(); persistItem( scope, item ); @@ -55,15 +58,16 @@ public void testMergeDetachedEntityWithIdentityId(SessionFactoryScope scope) { // for generated id Hibernate can detect that the instance is not transient // so because of the discrepancy of the null version // that implies a transient instance an exception should be thrown - Assertions.assertThrows( PropertyValueException.class, () -> - scope.inTransaction( - session -> { - IdentityGeneratedIdItem item1 = new IdentityGeneratedIdItem(); - item1.id = item.getId(); - item1.setName( ITEM_UPDATED_NAME ); - session.merge( item1 ); - } - ) + Assertions.assertThrows( + PropertyValueException.class, () -> + scope.inTransaction( + session -> { + IdentityGeneratedIdItem item1 = new IdentityGeneratedIdItem(); + item1.id = item.getId(); + item1.setName( ITEM_UPDATED_NAME ); + session.merge( item1 ); + } + ) ); assertItemHasNotBeenUpdated( item, scope ); @@ -82,15 +86,16 @@ public void testMergeDetachedEntityWithSequenceId(SessionFactoryScope scope) { // for generated id Hibernate can detect that the instance is not transient // so because of the discrepancy of the null version // that implies a transient instance an exception should be thrown - Assertions.assertThrows( PropertyValueException.class, () -> - scope.inTransaction( - session -> { - SequenceGeneratedIdItem item1 = new SequenceGeneratedIdItem(); - item1.id = item.getId(); - item1.setName( ITEM_UPDATED_NAME ); - session.merge( item1 ); - } - ) + Assertions.assertThrows( + PropertyValueException.class, () -> + scope.inTransaction( + session -> { + SequenceGeneratedIdItem item1 = new SequenceGeneratedIdItem(); + item1.id = item.getId(); + item1.setName( ITEM_UPDATED_NAME ); + session.merge( item1 ); + } + ) ); assertItemHasNotBeenUpdated( item, scope ); @@ -109,15 +114,16 @@ public void testMergeDetachedEntityWithTableGerneratedId(SessionFactoryScope sco // for generated id Hibernate can detect that the instance is not transient // so because of the discrepancy of the null version // that implies a transient instance an exception should be thrown - Assertions.assertThrows( PropertyValueException.class, () -> - scope.inTransaction( - session -> { - TableGeneratedIdItem item1 = new TableGeneratedIdItem(); - item1.id = item.getId(); - item1.setName( ITEM_UPDATED_NAME ); - session.merge( item1 ); - } - ) + Assertions.assertThrows( + PropertyValueException.class, () -> + scope.inTransaction( + session -> { + TableGeneratedIdItem item1 = new TableGeneratedIdItem(); + item1.id = item.getId(); + item1.setName( ITEM_UPDATED_NAME ); + session.merge( item1 ); + } + ) ); assertItemHasNotBeenUpdated( item, scope ); @@ -136,15 +142,16 @@ public void testMergeDetachedEntityWithUUIDId(SessionFactoryScope scope) { // for generated id Hibernate can detect that the instance is not transient // so because of the discrepancy of the null version // that implies a transient instance an exception should be thrownAssertions.assertThrows( HibernateException.class, () -> - Assertions.assertThrows( PropertyValueException.class, () -> - scope.inTransaction( - session -> { - UUIDIdItem item1 = new UUIDIdItem(); - item1.id = item.getId(); - item1.setName( ITEM_UPDATED_NAME ); - session.merge( item1 ); - } - ) + Assertions.assertThrows( + PropertyValueException.class, () -> + scope.inTransaction( + session -> { + UUIDIdItem item1 = new UUIDIdItem(); + item1.id = item.getId(); + item1.setName( ITEM_UPDATED_NAME ); + session.merge( item1 ); + } + ) ); assertItemHasNotBeenUpdated( item, scope ); @@ -163,13 +170,14 @@ public void testMergeDetachedEntityWithAssignedId(SessionFactoryScope scope) { // Hibernate for assigned id does not detect that this is a detached instance so consider it // a transient instance because of the null version // so a constraint exception is thrown when Hibernate tries to persist it - Assertions.assertThrows( ConstraintViolationException.class, () -> - scope.inTransaction( - session -> { - AssignedIdItem item1 = new AssignedIdItem( 1l, ITEM_UPDATED_NAME ); - session.merge( item1 ); - } - ) + Assertions.assertThrows( + ConstraintViolationException.class, () -> + scope.inTransaction( + session -> { + AssignedIdItem item1 = new AssignedIdItem( 1l, ITEM_UPDATED_NAME ); + session.merge( item1 ); + } + ) ); assertItemHasNotBeenUpdated( item, scope ); diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/common/connections/BaseTransactionIsolationConfigTest.java b/hibernate-testing/src/main/java/org/hibernate/testing/common/connections/BaseTransactionIsolationConfigTest.java index 88d39c68db8a..3afcbeace26a 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/common/connections/BaseTransactionIsolationConfigTest.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/common/connections/BaseTransactionIsolationConfigTest.java @@ -9,6 +9,7 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.internal.util.PropertiesHelper; import org.hibernate.service.spi.Configurable; @@ -16,6 +17,7 @@ import org.hibernate.service.spi.Stoppable; import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -30,6 +32,7 @@ protected void augmentConfigurationSettings(Properties properties) { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "Looks like SERIALIZABLE is not supported") public void testSettingIsolationAsNumeric() throws Exception { Properties properties = Environment.getProperties(); augmentConfigurationSettings( properties ); @@ -54,6 +57,7 @@ public void testSettingIsolationAsNumeric() throws Exception { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "Looks like SERIALIZABLE is not supported") public void testSettingIsolationAsNumericString() throws Exception { Properties properties = Environment.getProperties(); augmentConfigurationSettings( properties ); @@ -78,6 +82,7 @@ public void testSettingIsolationAsNumericString() throws Exception { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "Looks like SERIALIZABLE is not supported") public void testSettingIsolationAsName() throws Exception { Properties properties = Environment.getProperties(); augmentConfigurationSettings( properties ); @@ -102,6 +107,7 @@ public void testSettingIsolationAsName() throws Exception { } @Test + @SkipForDialect( dialectClass = GaussDBDialect.class, reason = "Looks like SERIALIZABLE is not supported") public void testSettingIsolationAsNameAlt() throws Exception { Properties properties = Environment.getProperties(); augmentConfigurationSettings( properties ); diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java index ea7a8b5a0f7a..8108cc0f1c55 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java @@ -47,6 +47,7 @@ import org.hibernate.dialect.CockroachDialect; import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.GaussDBDialect; import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.HANADialect; import org.hibernate.dialect.HSQLDialect; @@ -427,8 +428,8 @@ public boolean apply(Dialect dialect) { public static class SupportsOrderByInCorrelatedSubquery implements DialectFeatureCheck { public boolean apply(Dialect dialect) { return dialect.supportsOrderByInSubquery() - // For some reason, HANA doesn't support order by in correlated subqueries... - && !( dialect instanceof HANADialect ); + // For some reason, HANA doesn't support order by in correlated subqueries... + && !( dialect instanceof HANADialect ); } } @@ -459,15 +460,15 @@ public boolean apply(Dialect dialect) { public static class SupportsStringAggregation implements DialectFeatureCheck { public boolean apply(Dialect dialect) { return dialect instanceof H2Dialect - || dialect instanceof HSQLDialect - || dialect instanceof MySQLDialect - || dialect instanceof PostgreSQLDialect - || dialect instanceof HANADialect - || dialect instanceof CockroachDialect - || dialect instanceof DB2Dialect - || dialect instanceof OracleDialect - || dialect instanceof SpannerDialect - || dialect instanceof SQLServerDialect; + || dialect instanceof HSQLDialect + || dialect instanceof MySQLDialect + || dialect instanceof PostgreSQLDialect + || dialect instanceof HANADialect + || dialect instanceof CockroachDialect + || dialect instanceof DB2Dialect + || dialect instanceof OracleDialect + || dialect instanceof SpannerDialect + || dialect instanceof SQLServerDialect; } } @@ -550,6 +551,7 @@ public boolean apply(Dialect dialect) { || dialect instanceof H2Dialect || dialect instanceof SQLServerDialect || dialect instanceof PostgreSQLDialect + || dialect instanceof GaussDBDialect || dialect instanceof DB2Dialect || dialect instanceof OracleDialect || dialect instanceof SybaseDialect @@ -562,7 +564,7 @@ public static class SupportsStructAggregate implements DialectFeatureCheck { public boolean apply(Dialect dialect) { try { return dialect.getAggregateSupport() != null - && dialect.getAggregateSupport().aggregateComponentCustomReadExpression( + && dialect.getAggregateSupport().aggregateComponentCustomReadExpression( "", "", "", @@ -589,7 +591,7 @@ public static class SupportsJsonAggregate implements DialectFeatureCheck { public boolean apply(Dialect dialect) { try { return dialect.getAggregateSupport() != null - && dialect.getAggregateSupport().aggregateComponentCustomReadExpression( + && dialect.getAggregateSupport().aggregateComponentCustomReadExpression( "", "", "", @@ -616,7 +618,7 @@ public static class SupportsXmlAggregate implements DialectFeatureCheck { public boolean apply(Dialect dialect) { try { return dialect.getAggregateSupport() != null - && dialect.getAggregateSupport().aggregateComponentCustomReadExpression( + && dialect.getAggregateSupport().aggregateComponentCustomReadExpression( "", "", "", @@ -642,8 +644,7 @@ public boolean apply(Dialect dialect) { public static class SupportsJsonComponentUpdate implements DialectFeatureCheck { public boolean apply(Dialect dialect) { try { - dialect.getAggregateSupport().requiresAggregateCustomWriteExpressionRenderer( SqlTypes.JSON ); - return true; + return dialect.getAggregateSupport().requiresAggregateCustomWriteExpressionRenderer( SqlTypes.JSON ); } catch (UnsupportedOperationException | IllegalArgumentException e) { return false; @@ -654,8 +655,7 @@ public boolean apply(Dialect dialect) { public static class SupportsXmlComponentUpdate implements DialectFeatureCheck { public boolean apply(Dialect dialect) { try { - dialect.getAggregateSupport().requiresAggregateCustomWriteExpressionRenderer( SqlTypes.SQLXML ); - return true; + return dialect.getAggregateSupport().requiresAggregateCustomWriteExpressionRenderer( SqlTypes.SQLXML ); } catch (UnsupportedOperationException | IllegalArgumentException e) { return false; @@ -678,9 +678,9 @@ public boolean apply(Dialect dialect) { public static class SupportsJsonQueryNestedPath implements DialectFeatureCheck { public boolean apply(Dialect dialect) { return definesFunction( dialect, "json_query" ) - && !( dialect instanceof SQLServerDialect ) - && !( dialect instanceof H2Dialect ) - && !( dialect instanceof CockroachDialect ); + && !( dialect instanceof SQLServerDialect ) + && !( dialect instanceof H2Dialect ) + && !( dialect instanceof CockroachDialect ); } } @@ -705,14 +705,14 @@ public boolean apply(Dialect dialect) { public static class SupportsJsonValueErrorBehavior implements DialectFeatureCheck { public boolean apply(Dialect dialect) { return definesFunction( dialect, "json_value" ) - // H2 emulation doesn't support error behavior - && !( dialect instanceof H2Dialect ) - // MariaDB simply doesn't support the on error and on empty clauses - && !( dialect instanceof MariaDBDialect ) - // Cockroach doesn't have a native json_value function - && !( dialect instanceof CockroachDialect ) - // PostgreSQL added support for native json_value in version 17 - && ( !( dialect instanceof PostgreSQLDialect ) || dialect.getVersion().isSameOrAfter( 17 ) ); + // H2 emulation doesn't support error behavior + && !( dialect instanceof H2Dialect ) + // MariaDB simply doesn't support the on error and on empty clauses + && !( dialect instanceof MariaDBDialect ) + // Cockroach doesn't have a native json_value function + && !( dialect instanceof CockroachDialect ) + // PostgreSQL added support for native json_value in version 17 + && ( !( dialect instanceof PostgreSQLDialect ) || dialect.getVersion().isSameOrAfter( 17 ) ); } } @@ -725,8 +725,8 @@ public boolean apply(Dialect dialect) { public static class SupportsJsonObjectAgg implements DialectFeatureCheck { public boolean apply(Dialect dialect) { return definesFunction( dialect, "json_objectagg" ) - // Bug in HSQL: https://sourceforge.net/p/hsqldb/bugs/1718/ - && !( dialect instanceof HSQLDialect ); + // Bug in HSQL: https://sourceforge.net/p/hsqldb/bugs/1718/ + && !( dialect instanceof HSQLDialect ); } } @@ -1018,8 +1018,8 @@ public static class SupportsUnicodeNClob implements DialectFeatureCheck { @Override public boolean apply(Dialect dialect) { return !(dialect instanceof SybaseASEDialect aseDialect) - // The jconn driver apparently doesn't support unicode characters - || aseDialect.getDriverKind() == SybaseDriverKind.JTDS; + // The jconn driver apparently doesn't support unicode characters + || aseDialect.getDriverKind() == SybaseDriverKind.JTDS; } } diff --git a/local-build-plugins/src/main/groovy/local.databases.gradle b/local-build-plugins/src/main/groovy/local.databases.gradle index 150ec7f19236..e09ffc0e12af 100644 --- a/local-build-plugins/src/main/groovy/local.databases.gradle +++ b/local-build-plugins/src/main/groovy/local.databases.gradle @@ -75,6 +75,21 @@ ext { // 'jdbc.datasource' : 'org.postgresql.ds.PGSimpleDataSource', 'connection.init_sql' : '' ], + gaussdb : [ + 'db.dialect' : 'org.hibernate.dialect.GaussDBDialect', + 'jdbc.driver' : 'com.huawei.gaussdb.jdbc.Driver', +// 'jdbc.user' : 'root', +// 'jdbc.pass' : 'czd@1106403012', + 'jdbc.user' : 'hibernate_orm_test', + 'jdbc.pass' : 'Hibernate_orm_test@1234', +// 'jdbc.user' : 'gaussdb', +// 'jdbc.pass' : 'OpenGauss123456@Go', + // Disable prepared statement caching to avoid issues with changing schemas + // Make batch verification work, see https://bbs.huaweicloud.com/forum/thread-02104174303512776081-1-1.html + 'jdbc.url' : 'jdbc:gaussdb://' + dbHost + '/hibernate_orm_test?currentSchema=test&preparedStatementCacheQueries=0&batchMode=off', + 'jdbc.datasource' : 'com.huawei.gaussdb.jdbc.Driver', + 'connection.init_sql': '' + ], edb_ci : [ 'db.dialect' : 'org.hibernate.dialect.PostgresPlusDialect', 'jdbc.driver': 'org.postgresql.Driver', diff --git a/local-build-plugins/src/main/groovy/local.java-module.gradle b/local-build-plugins/src/main/groovy/local.java-module.gradle index 40499736c718..c61cd5f561ec 100644 --- a/local-build-plugins/src/main/groovy/local.java-module.gradle +++ b/local-build-plugins/src/main/groovy/local.java-module.gradle @@ -73,6 +73,7 @@ dependencies { testRuntimeOnly jdbcLibs.mssql testRuntimeOnly jdbcLibs.informix testRuntimeOnly jdbcLibs.cockroachdb + testRuntimeOnly jdbcLibs.gaussdb testRuntimeOnly jdbcLibs.sybase testRuntimeOnly rootProject.fileTree(dir: 'drivers', include: '*.jar') diff --git a/settings.gradle b/settings.gradle index b8c10b4d326d..e634f0e87acd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -227,6 +227,7 @@ dependencyResolutionManagement { def mysqlVersion = version "mysql", "9.2.0" def oracleVersion = version "oracle", "23.7.0.25.01" def pgsqlVersion = version "pgsql", "42.7.4" + def gaussdbVersion = version "gaussdb", "506.0.0.b058" def sybaseVersion = version "sybase", "1.3.1" def tidbVersion = version "tidb", mysqlVersion def altibaseVersion = version "altibase", "7.3.0.0.3" @@ -238,6 +239,7 @@ dependencyResolutionManagement { library( "derbyTools", "org.apache.derby", "derbytools" ).versionRef( derbyVersion ) library( "postgresql", "org.postgresql", "postgresql" ).versionRef( pgsqlVersion ) library( "cockroachdb", "org.postgresql", "postgresql" ).versionRef( pgsqlVersion ) + library( "gaussdb", "com.huaweicloud.gaussdb", "gaussdbjdbc" ).versionRef( gaussdbVersion ) library( "mysql", "com.mysql", "mysql-connector-j" ).versionRef( mysqlVersion ) library( "tidb", "com.mysql", "mysql-connector-j" ).versionRef( tidbVersion ) library( "mariadb", "org.mariadb.jdbc", "mariadb-java-client" ).versionRef( mariadbVersion )