HHH-18892 add hex() function

This commit is contained in:
Gavin King 2024-12-03 21:18:01 +01:00
parent c73a12ced6
commit 1a5db3bf42
14 changed files with 38 additions and 1 deletions

View File

@ -841,6 +841,7 @@ Naturally, there are a good number of functions for working with strings.
| `replace()` | Replace every occurrence of a pattern in a string | `replace(str, patt, rep)` | ✔ / ✖ | `replace()` | Replace every occurrence of a pattern in a string | `replace(str, patt, rep)` | ✔ / ✖
| `repeat()` | Concatenate a string with itself multiple times | `repeat(str, times)` | ✖ / ✖ | `repeat()` | Concatenate a string with itself multiple times | `repeat(str, times)` | ✖ / ✖
| `collate()` | Select a collation | `collate(p.name as collation)` | ✖ / ✖ | `collate()` | Select a collation | `collate(p.name as collation)` | ✖ / ✖
| `hex()` | Encode a binary value as a hexadecimal string | `hex(image.bytes)` | ✖ / ✖
|=== |===
Let's take a closer look at just some of these. Let's take a closer look at just some of these.

View File

@ -503,6 +503,7 @@ public class CockroachDialect extends Dialect {
); );
functionContributions.getFunctionRegistry().registerAlternateKey( "truncate", "trunc" ); functionContributions.getFunctionRegistry().registerAlternateKey( "truncate", "trunc" );
functionFactory.hex( "encode(?1, 'hex')" );
functionFactory.sha( "digest(?1, 'sha256')" ); functionFactory.sha( "digest(?1, 'sha256')" );
functionFactory.md5( "digest(?1, 'md5')" ); functionFactory.md5( "digest(?1, 'md5')" );
} }

View File

@ -453,6 +453,7 @@ public class DB2Dialect extends Dialect {
functionFactory.unnest_db2( getMaximumSeriesSize() ); functionFactory.unnest_db2( getMaximumSeriesSize() );
functionFactory.generateSeries_recursive( getMaximumSeriesSize(), false, true ); functionFactory.generateSeries_recursive( getMaximumSeriesSize(), false, true );
functionFactory.hex( "hex(?1)" );
functionFactory.sha( "hash(?1, 2)" ); functionFactory.sha( "hash(?1, 2)" );
functionFactory.md5( "hash(?1, 0)" ); functionFactory.md5( "hash(?1, 0)" );
} }

View File

@ -369,6 +369,7 @@ public class H2Dialect extends Dialect {
functionFactory.generateSeries_h2( getMaximumSeriesSize() ); functionFactory.generateSeries_h2( getMaximumSeriesSize() );
functionFactory.jsonTable_h2( getMaximumArraySize() ); functionFactory.jsonTable_h2( getMaximumArraySize() );
functionFactory.hex( "rawtohex(?1)" );
functionFactory.sha( "hash('SHA-256', ?1)" ); functionFactory.sha( "hash('SHA-256', ?1)" );
functionFactory.md5( "hash('MD5', ?1)" ); functionFactory.md5( "hash('MD5', ?1)" );
} }

View File

@ -518,6 +518,7 @@ public class HANADialect extends Dialect {
// functionFactory.xmlextract(); // functionFactory.xmlextract();
functionFactory.generateSeries_hana( getMaximumSeriesSize() ); functionFactory.generateSeries_hana( getMaximumSeriesSize() );
functionFactory.hex( "to_hex(?1)" );
functionFactory.sha( "hash_sha256(?1)" ); functionFactory.sha( "hash_sha256(?1)" );
functionFactory.md5( "hash_md5(?1)" ); functionFactory.md5( "hash_md5(?1)" );
} }

View File

@ -222,6 +222,8 @@ public class HSQLDialect extends Dialect {
functionContributions.getTypeConfiguration(), functionContributions.getTypeConfiguration(),
SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER
) ); ) );
functionFactory.hex( "hex(?1)" );
} }
/** /**

View File

@ -687,6 +687,7 @@ public class MySQLDialect extends Dialect {
functionFactory.generateSeries_recursive( getMaximumSeriesSize(), false, false ); functionFactory.generateSeries_recursive( getMaximumSeriesSize(), false, false );
} }
functionFactory.hex( "hex(?1)" );
functionFactory.sha( "unhex(sha2(?1, 256))" ); functionFactory.sha( "unhex(sha2(?1, 256))" );
functionFactory.md5( "unhex(md5(?1))" ); functionFactory.md5( "unhex(md5(?1))" );
} }

View File

@ -441,6 +441,7 @@ public class OracleDialect extends Dialect {
functionFactory.generateSeries_recursive( getMaximumSeriesSize(), true, false ); functionFactory.generateSeries_recursive( getMaximumSeriesSize(), true, false );
functionFactory.jsonTable_oracle(); functionFactory.jsonTable_oracle();
functionFactory.hex( "rawtohex(?1)" );
functionFactory.sha( "standard_hash(?1, 'SHA256')" ); functionFactory.sha( "standard_hash(?1, 'SHA256')" );
functionFactory.md5( "standard_hash(?1, 'MD5')" ); functionFactory.md5( "standard_hash(?1, 'MD5')" );
} }

View File

@ -690,6 +690,7 @@ public class PostgreSQLDialect extends Dialect {
} }
functionFactory.generateSeries( null, "ordinality", false ); functionFactory.generateSeries( null, "ordinality", false );
functionFactory.hex( "encode(?1, 'hex')" );
functionFactory.sha( "sha256(?1)" ); functionFactory.sha( "sha256(?1)" );
functionFactory.md5( "decode(md5(?1), 'hex')" ); functionFactory.md5( "decode(md5(?1), 'hex')" );
} }

View File

@ -488,6 +488,7 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
} }
} }
functionFactory.hex( "convert(varchar(MAX), ?1, 2)" );
functionFactory.sha( "hashbytes('SHA2_256', ?1)" ); functionFactory.sha( "hashbytes('SHA2_256', ?1)" );
functionFactory.md5( "hashbytes('MD5', ?1)" ); functionFactory.md5( "hashbytes('MD5', ?1)" );
} }

View File

@ -389,7 +389,8 @@ public class CommonFunctionFactory {
} }
/** /**
* CockroachDB lacks implicit casting: https://github.com/cockroachdb/cockroach/issues/89965 * CockroachDB lacks
* <a href="https://github.com/cockroachdb/cockroach/issues/89965">implicit casting</a>
*/ */
public void median_percentileCont_castDouble() { public void median_percentileCont_castDouble() {
functionRegistry.patternDescriptorBuilder( functionRegistry.patternDescriptorBuilder(
@ -2325,6 +2326,14 @@ public class CommonFunctionFactory {
.register(); .register();
} }
public void hex(String pattern) {
functionRegistry.patternDescriptorBuilder( "hex", pattern )
.setInvariantType(stringType)
.setParameterTypes( BINARY )
.setExactArgumentCount( 1 )
.register();
}
public void md5(String pattern) { public void md5(String pattern) {
functionRegistry.patternDescriptorBuilder( "md5", pattern ) functionRegistry.patternDescriptorBuilder( "md5", pattern )
.setInvariantType(binaryType) .setInvariantType(binaryType)

View File

@ -248,6 +248,7 @@ public class ArgumentTypesValidator implements ArgumentsValidator {
case TEMPORAL -> jdbcType.isTemporal(); case TEMPORAL -> jdbcType.isTemporal();
case DATE -> jdbcType.hasDatePart(); case DATE -> jdbcType.hasDatePart();
case TIME -> jdbcType.hasTimePart(); case TIME -> jdbcType.hasTimePart();
case BINARY -> jdbcType.isBinary();
case SPATIAL -> jdbcType.isSpatial(); case SPATIAL -> jdbcType.isSpatial();
case JSON -> jdbcType.isJson(); case JSON -> jdbcType.isJson();
case IMPLICIT_JSON -> jdbcType.isImplicitJson(); case IMPLICIT_JSON -> jdbcType.isImplicitJson();

View File

@ -48,6 +48,10 @@ public enum FunctionParameterType {
* a logical expression (predicate) * a logical expression (predicate)
*/ */
BOOLEAN, BOOLEAN,
/**
* @see org.hibernate.type.SqlTypes#isBinaryType(int)
*/
BINARY,
/** /**
* Indicates a parameter that accepts any type * Indicates a parameter that accepts any type
*/ */

View File

@ -23,6 +23,7 @@ import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.PostgresPlusDialect; import org.hibernate.dialect.PostgresPlusDialect;
import org.hibernate.dialect.SQLServerDialect; import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseASEDialect;
import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.SybaseDialect;
import org.hibernate.dialect.TiDBDialect; import org.hibernate.dialect.TiDBDialect;
import org.hibernate.query.sqm.produce.function.FunctionArgumentException; import org.hibernate.query.sqm.produce.function.FunctionArgumentException;
@ -62,6 +63,7 @@ import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -2627,4 +2629,14 @@ public class FunctionTests {
} }
}); });
} }
@Test
@SkipForDialect(dialectClass = SybaseASEDialect.class)
public void testHexFunction(SessionFactoryScope scope) {
scope.inTransaction(s -> {
assertEquals( "DEADBEEF",
s.createSelectionQuery("select hex({0xDE, 0xAD, 0xBE, 0xEF})", String.class)
.getSingleResult().toUpperCase( Locale.ROOT ) );
});
}
} }