reworked approach to Dialect column type customization
This commit is contained in:
parent
103e5c658b
commit
eb3bcdb94a
|
@ -28,6 +28,8 @@ import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
|||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
|
||||
/**
|
||||
* SQL Dialect for Sybase Anywhere
|
||||
* (Tested on ASA 8.x)
|
||||
|
@ -35,31 +37,48 @@ import org.hibernate.sql.exec.spi.JdbcOperation;
|
|||
public class SybaseAnywhereDialect extends SybaseDialect {
|
||||
|
||||
public SybaseAnywhereDialect() {
|
||||
this( DatabaseVersion.make( 8 ), false );
|
||||
this( DatabaseVersion.make( 8 ) );
|
||||
}
|
||||
|
||||
public SybaseAnywhereDialect(DatabaseVersion version) {
|
||||
this(version, null);
|
||||
}
|
||||
|
||||
public SybaseAnywhereDialect(DialectResolutionInfo info){
|
||||
this(
|
||||
info,
|
||||
info.getDriverName() != null && info.getDriverName().contains( "jTDS" )
|
||||
);
|
||||
this( info.makeCopy(), info );
|
||||
registerKeywords( info );
|
||||
}
|
||||
|
||||
public SybaseAnywhereDialect(DatabaseVersion version, boolean jtdsDriver) {
|
||||
super( version, jtdsDriver );
|
||||
public SybaseAnywhereDialect(DatabaseVersion version, DialectResolutionInfo info) {
|
||||
super( version, info );
|
||||
}
|
||||
|
||||
registerColumnType( Types.BIGINT, "bigint" );
|
||||
registerColumnType( Types.DATE, "date" );
|
||||
registerColumnType( Types.TIME, "time" );
|
||||
registerColumnType( Types.TIMESTAMP, "timestamp" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp with time zone" );
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
switch (jdbcTypeCode) {
|
||||
case DATE:
|
||||
return "date";
|
||||
case TIME:
|
||||
return "time";
|
||||
case TIMESTAMP:
|
||||
return "timestamp";
|
||||
case TIMESTAMP_WITH_TIMEZONE:
|
||||
return "timestamp with time zone";
|
||||
|
||||
registerColumnType( Types.VARCHAR, "long varchar)" );
|
||||
registerColumnType( Types.NVARCHAR, "long nvarchar)" );
|
||||
//these types hold up to 2 GB
|
||||
case LONGVARCHAR:
|
||||
return "long varchar";
|
||||
case LONGNVARCHAR:
|
||||
return "long nvarchar";
|
||||
case LONGVARBINARY:
|
||||
return "long binary";
|
||||
|
||||
//note: 'binary' is actually a synonym for 'varbinary'
|
||||
registerColumnType( Types.VARBINARY, "long binary)" );
|
||||
case NCLOB:
|
||||
return "ntext";
|
||||
|
||||
default:
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -150,7 +169,6 @@ public class SybaseAnywhereDialect extends SybaseDialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map<String, String[]> keyColumnNames) {
|
||||
return getVersion().isBefore( 10 )
|
||||
? super.applyLocksToSql( sql, aliasedLockOptions, keyColumnNames )
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.LockMode;
|
|||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.dialect.function.CastingConcatFunction;
|
||||
import org.hibernate.dialect.function.TransactSQLStrFunction;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.query.NullOrdering;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||
|
@ -41,39 +42,53 @@ import java.sql.Types;
|
|||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
|
||||
/**
|
||||
* An abstract base class for Sybase and MS SQL Server dialects.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public abstract class AbstractTransactSQLDialect extends Dialect {
|
||||
public AbstractTransactSQLDialect() {
|
||||
super();
|
||||
|
||||
registerColumnType( Types.BOOLEAN, "bit" );
|
||||
|
||||
//'tinyint' is an unsigned type in Sybase and
|
||||
//SQL Server, holding values in the range 0-255
|
||||
//see HHH-6779
|
||||
registerColumnType( Types.TINYINT, "smallint" );
|
||||
|
||||
//it's called 'int' not 'integer'
|
||||
registerColumnType( Types.INTEGER, "int" );
|
||||
|
||||
//note that 'real' is double precision on SQL Server, single precision on Sybase
|
||||
//but 'float' is single precision on Sybase, double precision on SQL Server
|
||||
|
||||
registerColumnType( Types.DATE, "datetime" );
|
||||
registerColumnType( Types.TIME, "datetime" );
|
||||
registerColumnType( Types.TIMESTAMP, "datetime" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "datetime" );
|
||||
|
||||
registerColumnType( Types.BLOB, "image" );
|
||||
registerColumnType( Types.CLOB, "text" );
|
||||
|
||||
public AbstractTransactSQLDialect(DatabaseVersion version, DialectResolutionInfo info) {
|
||||
super(version, info);
|
||||
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, NO_BATCH );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
// note that 'real' is double precision on SQL Server, single precision on Sybase
|
||||
// but 'float' is single precision on Sybase, double precision on SQL Server
|
||||
switch(jdbcTypeCode) {
|
||||
case BOOLEAN:
|
||||
return "bit";
|
||||
|
||||
case TINYINT:
|
||||
//'tinyint' is an unsigned type in Sybase and
|
||||
//SQL Server, holding values in the range 0-255
|
||||
//see HHH-6779
|
||||
return "smallint";
|
||||
case INTEGER:
|
||||
//it's called 'int' not 'integer'
|
||||
return "int";
|
||||
|
||||
case DATE:
|
||||
case TIME:
|
||||
case TIMESTAMP:
|
||||
case TIME_WITH_TIMEZONE:
|
||||
return "datetime";
|
||||
|
||||
case BLOB:
|
||||
return "image";
|
||||
case CLOB:
|
||||
return "text";
|
||||
|
||||
default:
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcType resolveSqlTypeDescriptor(
|
||||
String columnTypeName,
|
||||
|
|
|
@ -8,11 +8,12 @@ package org.hibernate.dialect;
|
|||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
|
@ -55,6 +56,7 @@ import jakarta.persistence.TemporalType;
|
|||
|
||||
import static org.hibernate.query.TemporalUnit.DAY;
|
||||
import static org.hibernate.query.TemporalUnit.NATIVE;
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros;
|
||||
|
@ -70,7 +72,6 @@ public class CockroachDialect extends Dialect {
|
|||
|
||||
// * no support for java.sql.Clob
|
||||
|
||||
private final DatabaseVersion version;
|
||||
private final PostgreSQLDriverKind driverKind;
|
||||
|
||||
public CockroachDialect() {
|
||||
|
@ -88,45 +89,56 @@ public class CockroachDialect extends Dialect {
|
|||
}
|
||||
|
||||
public CockroachDialect(DatabaseVersion version, PostgreSQLDriverKind driverKind) {
|
||||
super();
|
||||
|
||||
this.version = version;
|
||||
super(version);
|
||||
this.driverKind = driverKind;
|
||||
}
|
||||
|
||||
registerColumnType( Types.TINYINT, "smallint" ); //no tinyint
|
||||
|
||||
//use 'string' instead of 'varchar'
|
||||
registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "string($l)");
|
||||
registerColumnType( Types.VARCHAR, "string");
|
||||
|
||||
//no binary/varbinary
|
||||
registerColumnType( Types.VARBINARY, "bytes" );
|
||||
registerColumnType( Types.BINARY, "bytes" );
|
||||
|
||||
//no clob
|
||||
registerColumnType( Types.CLOB, "string" );
|
||||
|
||||
//no nchar/nvarchar
|
||||
registerColumnType( Types.NCHAR, "string($l)" );
|
||||
registerColumnType( Types.NVARCHAR, getMaxNVarcharLength(), "string($l)" );
|
||||
registerColumnType( Types.NVARCHAR, "string");
|
||||
|
||||
//no nclob
|
||||
registerColumnType( Types.NCLOB, "string" );
|
||||
|
||||
registerColumnType( SqlTypes.UUID, "uuid" );
|
||||
registerColumnType( SqlTypes.INTERVAL_SECOND, "interval second($s)" );
|
||||
|
||||
// Prefer jsonb if possible
|
||||
if ( getVersion().isSameOrAfter( 20, 0 ) ) {
|
||||
registerColumnType( SqlTypes.INET, "inet" );
|
||||
registerColumnType( SqlTypes.JSON, "jsonb" );
|
||||
}
|
||||
else {
|
||||
registerColumnType( SqlTypes.JSON, "json" );
|
||||
@Override
|
||||
protected List<Integer> getSupportedJdbcTypeCodes() {
|
||||
List<Integer> typeCodes = new ArrayList<>( super.getSupportedJdbcTypeCodes() );
|
||||
typeCodes.addAll( List.of(UUID, INTERVAL_SECOND, GEOMETRY, JSON) );
|
||||
if ( getVersion().isSameOrAfter( 20 ) ) {
|
||||
typeCodes.add(INET);
|
||||
}
|
||||
return typeCodes;
|
||||
}
|
||||
|
||||
registerColumnType( SqlTypes.GEOMETRY, "geometry" );
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
switch (jdbcTypeCode) {
|
||||
case TINYINT:
|
||||
return "smallint"; //no tinyint
|
||||
|
||||
case CHAR:
|
||||
case NCHAR:
|
||||
case VARCHAR:
|
||||
case NVARCHAR:
|
||||
return "string($l)";
|
||||
|
||||
case NCLOB:
|
||||
case CLOB:
|
||||
return "string";
|
||||
|
||||
case BINARY:
|
||||
case VARBINARY:
|
||||
case BLOB:
|
||||
return "bytes";
|
||||
|
||||
case INET:
|
||||
return "inet";
|
||||
case UUID:
|
||||
return "uuid";
|
||||
case GEOMETRY:
|
||||
return "geometry";
|
||||
case INTERVAL_SECOND:
|
||||
return "interval second($s)";
|
||||
|
||||
case JSON:
|
||||
// Prefer jsonb if possible
|
||||
return getVersion().isSameOrAfter( 20 ) ? "jsonb" : "json";
|
||||
default:
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -148,21 +160,21 @@ public class CockroachDialect extends Dialect {
|
|||
int precision,
|
||||
int scale,
|
||||
JdbcTypeRegistry jdbcTypeRegistry) {
|
||||
if ( jdbcTypeCode == SqlTypes.OTHER ) {
|
||||
if ( jdbcTypeCode == OTHER ) {
|
||||
switch ( columnTypeName ) {
|
||||
case "uuid":
|
||||
jdbcTypeCode = SqlTypes.UUID;
|
||||
jdbcTypeCode = UUID;
|
||||
break;
|
||||
case "json":
|
||||
case "jsonb":
|
||||
jdbcTypeCode = SqlTypes.JSON;
|
||||
jdbcTypeCode = JSON;
|
||||
break;
|
||||
case "inet":
|
||||
jdbcTypeCode = SqlTypes.INET;
|
||||
jdbcTypeCode = INET;
|
||||
break;
|
||||
case "geometry":
|
||||
case "geography":
|
||||
jdbcTypeCode = SqlTypes.GEOMETRY;
|
||||
jdbcTypeCode = GEOMETRY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -189,11 +201,6 @@ public class CockroachDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
super.initializeFunctionRegistry(queryEngine);
|
||||
|
|
|
@ -59,6 +59,8 @@ import java.sql.Types;
|
|||
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
|
||||
/**
|
||||
* An SQL dialect for DB2.
|
||||
*
|
||||
|
@ -75,8 +77,6 @@ public class DB2Dialect extends Dialect {
|
|||
private static final String FOR_SHARE_SKIP_LOCKED_SQL = FOR_SHARE_SQL + SKIP_LOCKED_SQL;
|
||||
private static final String FOR_UPDATE_SKIP_LOCKED_SQL = FOR_UPDATE_SQL + SKIP_LOCKED_SQL;
|
||||
|
||||
private final DatabaseVersion version;
|
||||
|
||||
private final LimitHandler limitHandler;
|
||||
private final UniqueDelegate uniqueDelegate;
|
||||
|
||||
|
@ -90,37 +90,7 @@ public class DB2Dialect extends Dialect {
|
|||
}
|
||||
|
||||
public DB2Dialect(DatabaseVersion version) {
|
||||
super();
|
||||
this.version = version;
|
||||
|
||||
registerColumnType( Types.TINYINT, "smallint" ); //no tinyint
|
||||
|
||||
//HHH-12827: map them both to the same type to avoid problems with schema update
|
||||
//Note that 31 is the maximum precision DB2 supports
|
||||
// registerColumnType( Types.DECIMAL, "decimal($p,$s)" );
|
||||
registerColumnType( Types.NUMERIC, "decimal($p,$s)" );
|
||||
|
||||
if ( getVersion().isBefore( 11 ) ) {
|
||||
registerColumnType( Types.BINARY, 254, "char($l) for bit data" ); //should use 'binary' since version 11
|
||||
registerColumnType( Types.BINARY, "varchar($l) for bit data" ); //should use 'binary' since version 11
|
||||
|
||||
registerColumnType( Types.VARBINARY, getMaxVarbinaryLength(), "varchar($l) for bit data" ); //should use 'varbinary' since version 11
|
||||
|
||||
//prior to DB2 11, the 'boolean' type existed,
|
||||
//but was not allowed as a column type
|
||||
registerColumnType( Types.BOOLEAN, "smallint" );
|
||||
}
|
||||
registerColumnType( Types.VARBINARY, "blob($l)" );
|
||||
|
||||
registerColumnType( Types.BLOB, "blob($l)" );
|
||||
registerColumnType( Types.CLOB, "clob($l)" );
|
||||
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp($p)" );
|
||||
registerColumnType( Types.TIME_WITH_TIMEZONE, "time" );
|
||||
|
||||
// The long varchar data type was deprecated in DB2 and shouldn't be used anymore
|
||||
registerColumnType( Types.VARCHAR, "clob($l)" );
|
||||
registerColumnType( Types.NVARCHAR, "nclob($l)" );
|
||||
super(version);
|
||||
|
||||
//not keywords, at least not in DB2 11,
|
||||
//but perhaps they were in older versions?
|
||||
|
@ -142,6 +112,51 @@ public class DB2Dialect extends Dialect {
|
|||
: DB2LimitHandler.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
if ( getVersion().isBefore( 11 ) ) {
|
||||
switch (jdbcTypeCode) {
|
||||
case BOOLEAN:
|
||||
// prior to DB2 11, the 'boolean' type existed,
|
||||
// but was not allowed as a column type
|
||||
return "smallint";
|
||||
case BINARY: // should use 'binary' since version 11
|
||||
case VARBINARY: // should use 'varbinary' since version 11
|
||||
return "varchar($l) for bit data";
|
||||
}
|
||||
}
|
||||
|
||||
switch (jdbcTypeCode) {
|
||||
case TINYINT:
|
||||
// no tinyint
|
||||
return "smallint";
|
||||
case NUMERIC:
|
||||
// HHH-12827: map them both to the same type to avoid problems with schema update
|
||||
// Note that 31 is the maximum precision DB2 supports
|
||||
return super.columnType(DECIMAL);
|
||||
case BLOB:
|
||||
return "blob($l)";
|
||||
case CLOB:
|
||||
return "clob($l)";
|
||||
case TIMESTAMP_WITH_TIMEZONE:
|
||||
return "timestamp($p)";
|
||||
case TIME_WITH_TIMEZONE:
|
||||
return "time";
|
||||
default:
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerDefaultColumnTypes(int maxVarcharLength, int maxNVarcharLength, int maxVarBinaryLength) {
|
||||
// Note: the 'long varchar' data type was deprecated in DB2 and shouldn't be used anymore
|
||||
super.registerDefaultColumnTypes(maxVarcharLength, maxNVarcharLength, maxVarBinaryLength);
|
||||
if ( getVersion().isBefore( 11 ) ) {
|
||||
// should use 'binary' since version 11
|
||||
registerColumnType( BINARY, 254, "char($l) for bit data" );
|
||||
}
|
||||
}
|
||||
|
||||
protected UniqueDelegate createUniqueDelegate() {
|
||||
return new DB2UniqueDelegate( this );
|
||||
}
|
||||
|
@ -151,11 +166,6 @@ public class DB2Dialect extends Dialect {
|
|||
return 32_672;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultDecimalPrecision() {
|
||||
//this is the maximum allowed in DB2
|
||||
|
@ -541,11 +551,11 @@ public class DB2Dialect extends Dialect {
|
|||
|
||||
final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration().getJdbcTypeDescriptorRegistry();
|
||||
|
||||
if ( version.isBefore( 11 ) ) {
|
||||
if ( getVersion().isBefore( 11 ) ) {
|
||||
jdbcTypeRegistry.addDescriptor( Types.BOOLEAN, SmallIntJdbcType.INSTANCE );
|
||||
// Binary literals were only added in 11. See https://www.ibm.com/support/knowledgecenter/SSEPGG_11.1.0/com.ibm.db2.luw.sql.ref.doc/doc/r0000731.html#d79816e393
|
||||
jdbcTypeRegistry.addDescriptor( Types.VARBINARY, VarbinaryJdbcType.INSTANCE_WITHOUT_LITERALS );
|
||||
if ( version.isBefore( 9, 7 ) ) {
|
||||
if ( getVersion().isBefore( 9, 7 ) ) {
|
||||
jdbcTypeRegistry.addDescriptor( Types.NUMERIC, DecimalJdbcType.INSTANCE );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ import java.sql.Types;
|
|||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers.useArgType;
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
|
||||
/**
|
||||
* Hibernate Dialect for Apache Derby / Cloudscape 10
|
||||
|
@ -91,8 +92,6 @@ public class DerbyDialect extends Dialect {
|
|||
// * can't select a parameter unless wrapped
|
||||
// in a cast or function call
|
||||
|
||||
private final DatabaseVersion version;
|
||||
|
||||
private final LimitHandler limitHandler;
|
||||
|
||||
public DerbyDialect(DialectResolutionInfo info) {
|
||||
|
@ -105,35 +104,7 @@ public class DerbyDialect extends Dialect {
|
|||
}
|
||||
|
||||
public DerbyDialect(DatabaseVersion version) {
|
||||
super();
|
||||
this.version = version;
|
||||
|
||||
if ( getVersion().isBefore( 10, 7 ) ) {
|
||||
registerColumnType( Types.BOOLEAN, "smallint" ); //no boolean before 10.7
|
||||
}
|
||||
registerColumnType( Types.TINYINT, "smallint" ); //no tinyint
|
||||
registerColumnType( Types.CHAR, 254, "char($l)" );
|
||||
|
||||
//HHH-12827: map them both to the same type to avoid problems with schema update
|
||||
//Note that 31 is the maximum precision Derby supports
|
||||
// registerColumnType( Types.DECIMAL, "decimal($p,$s)" );
|
||||
registerColumnType( Types.NUMERIC, "decimal($p,$s)" );
|
||||
|
||||
registerColumnType( Types.BINARY, 254, "char($l) for bit data" );
|
||||
registerColumnType( Types.BINARY, getMaxVarbinaryLength(), "varchar($l) for bit data" );
|
||||
registerColumnType( Types.BINARY, "long varchar for bit data" );
|
||||
registerColumnType( Types.VARBINARY, getMaxVarbinaryLength(), "varchar($l) for bit data" );
|
||||
registerColumnType( Types.VARBINARY, 32_700,"long varchar for bit data" );
|
||||
registerColumnType( Types.VARBINARY, "blob($l)" );
|
||||
|
||||
registerColumnType( Types.BLOB, "blob($l)" );
|
||||
registerColumnType( Types.CLOB, "clob($l)" );
|
||||
|
||||
registerColumnType( Types.TIMESTAMP, "timestamp" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp" );
|
||||
|
||||
registerColumnType( Types.VARCHAR, 32_700, "long varchar" );
|
||||
registerColumnType( Types.VARCHAR, "clob($l)" );
|
||||
super(version);
|
||||
|
||||
registerDerbyKeywords();
|
||||
|
||||
|
@ -144,6 +115,52 @@ public class DerbyDialect extends Dialect {
|
|||
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, NO_BATCH );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
if ( jdbcTypeCode == BOOLEAN && getVersion().isBefore( 10, 7 ) ) {
|
||||
return "smallint";
|
||||
}
|
||||
|
||||
switch (jdbcTypeCode) {
|
||||
case TINYINT:
|
||||
//no tinyint
|
||||
return "smallint";
|
||||
|
||||
case NUMERIC:
|
||||
// HHH-12827: map them both to the same type to avoid problems with schema update
|
||||
// Note that 31 is the maximum precision Derby supports
|
||||
return super.columnType(DECIMAL);
|
||||
|
||||
case VARBINARY:
|
||||
return "varchar($l) for bit data";
|
||||
|
||||
case BLOB:
|
||||
return "blob($l)";
|
||||
case CLOB:
|
||||
return "clob($l)";
|
||||
|
||||
case TIMESTAMP:
|
||||
case TIMESTAMP_WITH_TIMEZONE:
|
||||
return "timestamp";
|
||||
|
||||
default:
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerDefaultColumnTypes(int maxVarcharLength, int maxNVarcharLength, int maxVarBinaryLength) {
|
||||
super.registerDefaultColumnTypes(maxVarcharLength, maxNVarcharLength, maxVarBinaryLength);
|
||||
|
||||
//long vachar is the right type to use for lengths between 32_672 and 32_700
|
||||
registerColumnType( VARBINARY, 32_700,"long varchar for bit data" );
|
||||
registerColumnType( VARCHAR, 32_700, "long varchar" );
|
||||
|
||||
registerColumnType( BINARY, 254, "char($l) for bit data" );
|
||||
registerColumnType( BINARY, 32_672, "varchar($l) for bit data" );
|
||||
registerColumnType( BINARY, 32_700, "long varchar for bit data" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarcharLength() {
|
||||
return 32_672;
|
||||
|
@ -173,11 +190,6 @@ public class DerbyDialect extends Dialect {
|
|||
: Types.BOOLEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NationalizationSupport getNationalizationSupport() {
|
||||
return NationalizationSupport.IMPLICIT;
|
||||
|
|
|
@ -163,6 +163,7 @@ import jakarta.persistence.TemporalType;
|
|||
|
||||
import static java.lang.Math.ceil;
|
||||
import static java.lang.Math.log;
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_END;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_DATE;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_TIME;
|
||||
|
@ -223,23 +224,37 @@ public abstract class Dialect implements ConversionContext {
|
|||
|
||||
private final SizeStrategy sizeStrategy;
|
||||
|
||||
private final DatabaseVersion version;
|
||||
|
||||
// constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
* @deprecated provide a {@link DatabaseVersion}
|
||||
*/
|
||||
@Deprecated
|
||||
protected Dialect() {
|
||||
this(true);
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
protected Dialect(boolean autoRegisterColumnTypes) {
|
||||
protected Dialect(DatabaseVersion version) {
|
||||
this( version, null );
|
||||
}
|
||||
|
||||
protected Dialect(DatabaseVersion version, DialectResolutionInfo info) {
|
||||
this.version = version;
|
||||
uniqueDelegate = new DefaultUniqueDelegate( this );
|
||||
sizeStrategy = new SizeStrategyImpl();
|
||||
if (autoRegisterColumnTypes) {
|
||||
registerDefaultColumnTypes();
|
||||
}
|
||||
registerDefaultColumnTypes(info); // pass the info back down to the subclass in case it needs it (MySQL)
|
||||
registerHibernateTypes();
|
||||
registerDefaultKeywords();
|
||||
}
|
||||
|
||||
protected void registerDefaultColumnTypes() {
|
||||
/**
|
||||
* Register ANSI-standard column types using the length limits defined
|
||||
* by {@link #getMaxVarcharLength()}, {@link #getMaxNVarcharLength()},
|
||||
* and {@link #getMaxVarbinaryLength()}.
|
||||
*/
|
||||
protected void registerDefaultColumnTypes(DialectResolutionInfo info) {
|
||||
registerDefaultColumnTypes( getMaxVarcharLength(), getMaxNVarcharLength(), getMaxVarbinaryLength() );
|
||||
}
|
||||
|
||||
|
@ -249,55 +264,181 @@ public abstract class Dialect implements ConversionContext {
|
|||
* {@code Dialect} by calling {@link #registerColumnType(int,String)}
|
||||
* from the constructor.
|
||||
* <p>
|
||||
* Note that {@link Types#LONGVARCHAR}, {@link Types#LONGNVARCHAR}
|
||||
* This method is aware of the notion of a maximum length for each of
|
||||
* the types {@link Types#VARCHAR}, {@link Types#NVARCHAR}, and
|
||||
* {@link Types#VARBINARY}, usually the limits defined by
|
||||
* {@link #getMaxVarcharLength()}, {@link #getMaxNVarcharLength()},
|
||||
* and {@link #getMaxVarbinaryLength()}, and registers "long" types
|
||||
* for lengths exceeding the limits.
|
||||
* <p>
|
||||
* The "long" types {@link Types#LONGVARCHAR}, {@link Types#LONGNVARCHAR}
|
||||
* and {@link Types#LONGVARBINARY} are considered synonyms for their
|
||||
* non-{@code LONG} counterparts, with the only difference being that
|
||||
* a different default length is used: {@link org.hibernate.Length#LONG}
|
||||
* instead of {@link org.hibernate.Length#DEFAULT}. Concrete dialects
|
||||
* should usually avoid registering mappings for these JDBC types.
|
||||
* instead of {@link org.hibernate.Length#DEFAULT}.
|
||||
* <p>
|
||||
* Any registrations made by this method may be overridden by calling
|
||||
* {@link #registerColumnType(int, String)} explicitly. Alternatively,
|
||||
* the registrations may be customized by overriding
|
||||
* {@link #getSupportedJdbcTypeCodes()} and {@link #columnType(int)}.
|
||||
*
|
||||
* @param maxVarcharLength the maximum length of the {@link Types#VARCHAR} type
|
||||
* @param maxNVarcharLength the maximum length of the {@link Types#NVARCHAR} type
|
||||
* @param maxVarBinaryLength the maximum length of the {@link Types#VARBINARY} type
|
||||
*/
|
||||
protected void registerDefaultColumnTypes(int maxVarcharLength, int maxNVarcharLength, int maxVarBinaryLength) {
|
||||
registerColumnType( Types.BOOLEAN, "boolean" );
|
||||
for ( int typeCode : getSupportedJdbcTypeCodes() ) {
|
||||
switch (typeCode) {
|
||||
case VARCHAR:
|
||||
registerColumnType( typeCode, maxVarcharLength, columnType(typeCode) );
|
||||
registerColumnType( typeCode, columnType(LONGVARCHAR) );
|
||||
break;
|
||||
case NVARCHAR:
|
||||
registerColumnType( typeCode, maxNVarcharLength, columnType(typeCode) );
|
||||
registerColumnType( typeCode, columnType(LONGNVARCHAR) );
|
||||
break;
|
||||
case VARBINARY:
|
||||
registerColumnType( typeCode, maxVarBinaryLength, columnType(typeCode) );
|
||||
registerColumnType( typeCode, columnType(LONGVARBINARY) );
|
||||
break;
|
||||
default:
|
||||
registerColumnType( typeCode, columnType(typeCode) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerColumnType( Types.TINYINT, "tinyint" );
|
||||
registerColumnType( Types.SMALLINT, "smallint" );
|
||||
registerColumnType( Types.INTEGER, "integer" );
|
||||
registerColumnType( Types.BIGINT, "bigint" );
|
||||
/**
|
||||
* A list of JDBC types that we expect to be supported on all databases.
|
||||
*/
|
||||
private static final List<Integer> ANSI_SQL_TYPES = List.of(
|
||||
BOOLEAN,
|
||||
TINYINT, SMALLINT, INTEGER, BIGINT,
|
||||
REAL, FLOAT, DOUBLE,
|
||||
NUMERIC, DECIMAL,
|
||||
DATE,
|
||||
TIME, TIME_WITH_TIMEZONE,
|
||||
TIMESTAMP, TIMESTAMP_WITH_TIMEZONE,
|
||||
CHAR, VARCHAR, CLOB,
|
||||
NCHAR, NVARCHAR, NCLOB,
|
||||
BINARY, VARBINARY, BLOB
|
||||
);
|
||||
|
||||
registerColumnType( Types.REAL, "real" );
|
||||
registerColumnType( Types.FLOAT, "float($p)" );
|
||||
registerColumnType( Types.DOUBLE, "double precision" );
|
||||
/**
|
||||
* The JDBC type codes of types supported by this SQL dialect, from the lists
|
||||
* defined by {@link Types} and {@link SqlTypes}.
|
||||
* <p>
|
||||
* This method may be overridden by concrete {@code Dialect}s as an alternative
|
||||
* to calling {@link #registerColumnType(int, String)}. In this case,
|
||||
* {@link #columnType(int)} should also be overridden.
|
||||
* <p>
|
||||
* Note that {@link Types#LONGVARCHAR}, {@link Types#LONGNVARCHAR} and
|
||||
* {@link Types#LONGVARBINARY} are considered synonyms for their
|
||||
* non-{@code LONG} counterparts, and should not be included in the returned
|
||||
* array.
|
||||
*
|
||||
* @return an array of types from {@link SqlTypes}
|
||||
*
|
||||
* @see SqlTypes
|
||||
* @see #columnType(int)
|
||||
*/
|
||||
protected List<Integer> getSupportedJdbcTypeCodes() {
|
||||
return ANSI_SQL_TYPES;
|
||||
}
|
||||
|
||||
//these are pretty much synonyms, but are considered
|
||||
//separate types by the ANSI spec, and in some dialects
|
||||
registerColumnType( Types.NUMERIC, "numeric($p,$s)" );
|
||||
registerColumnType( Types.DECIMAL, "decimal($p,$s)" );
|
||||
/**
|
||||
* The column type name for a given JDBC type code defined in {@link Types} or
|
||||
* {@link SqlTypes}. This default implementation returns the ANSI-standard type
|
||||
* name.
|
||||
* <p>
|
||||
* This method may be overridden by concrete {@code Dialect}s as an alternative
|
||||
* to calling {@link #registerColumnType(int,String)}.
|
||||
*
|
||||
* @param jdbcTypeCode a JDBC type code
|
||||
* @return a column type name, with $l, $p, $s placeholders for length, precision, scale
|
||||
*
|
||||
* @see SqlTypes
|
||||
* @see #getSupportedJdbcTypeCodes()
|
||||
*/
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
switch (jdbcTypeCode) {
|
||||
case BOOLEAN:
|
||||
return "boolean";
|
||||
|
||||
registerColumnType( Types.DATE, "date" );
|
||||
registerColumnType( Types.TIME, "time" );
|
||||
registerColumnType( Types.TIMESTAMP, "timestamp($p)" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp($p) with time zone" );
|
||||
// type included here for completeness but note that
|
||||
// very few databases support it, and the general
|
||||
// advice is to caution against its use (for reasons,
|
||||
// check the comments in the Postgres documentation).
|
||||
registerColumnType( Types.TIME_WITH_TIMEZONE, "time with time zone" );
|
||||
case TINYINT:
|
||||
return "tinyint";
|
||||
case SMALLINT:
|
||||
return "smallint";
|
||||
case INTEGER:
|
||||
return "integer";
|
||||
case BIGINT:
|
||||
return "bigint";
|
||||
|
||||
registerColumnType( Types.BINARY, "binary($l)" );
|
||||
registerColumnType( Types.VARBINARY, maxVarBinaryLength, "varbinary($l)" );
|
||||
registerColumnType( Types.BLOB, "blob" );
|
||||
case FLOAT:
|
||||
// this is the floating point type we prefer!
|
||||
return "float($p)";
|
||||
case REAL:
|
||||
// this type has very unclear semantics in ANSI SQL,
|
||||
// so we avoid it and prefer float with an explicit
|
||||
// precision
|
||||
return "real";
|
||||
case DOUBLE:
|
||||
// this is just a more verbose way to write float(19)
|
||||
return "double precision";
|
||||
|
||||
registerColumnType( Types.CHAR, "char($l)" );
|
||||
registerColumnType( Types.VARCHAR, maxVarcharLength, "varchar($l)" );
|
||||
registerColumnType( Types.CLOB, "clob" );
|
||||
// these are pretty much synonyms, but are considered
|
||||
// separate types by the ANSI spec, and in some dialects
|
||||
case NUMERIC:
|
||||
return "numeric($p,$s)";
|
||||
case DECIMAL:
|
||||
return "decimal($p,$s)";
|
||||
|
||||
registerColumnType( Types.NCHAR, "nchar($l)" );
|
||||
registerColumnType( Types.NVARCHAR, maxNVarcharLength, "nvarchar($l)" );
|
||||
registerColumnType( Types.NCLOB, "nclob" );
|
||||
case DATE:
|
||||
return "date";
|
||||
case TIME:
|
||||
return "time";
|
||||
case TIME_WITH_TIMEZONE:
|
||||
// type included here for completeness but note that
|
||||
// very few databases support it, and the general
|
||||
// advice is to caution against its use (for reasons,
|
||||
// check the comments in the Postgres documentation).
|
||||
return "time with time zone";
|
||||
case TIMESTAMP:
|
||||
return "timestamp($p)";
|
||||
case TIMESTAMP_WITH_TIMEZONE:
|
||||
return "timestamp($p) with time zone";
|
||||
|
||||
case CHAR:
|
||||
return "char($l)";
|
||||
case VARCHAR:
|
||||
return "varchar($l)";
|
||||
case CLOB:
|
||||
return "clob";
|
||||
|
||||
case NCHAR:
|
||||
return "nchar($l)";
|
||||
case NVARCHAR:
|
||||
return "nvarchar($l)";
|
||||
case NCLOB:
|
||||
return "nclob";
|
||||
|
||||
case BINARY:
|
||||
return "binary($l)";
|
||||
case VARBINARY:
|
||||
return "varbinary($l)";
|
||||
case BLOB:
|
||||
return "blob";
|
||||
|
||||
// by default use the LOB mappings for the "long" types
|
||||
case LONGVARCHAR:
|
||||
return columnType(CLOB);
|
||||
case LONGNVARCHAR:
|
||||
return columnType(NCLOB);
|
||||
case LONGVARBINARY:
|
||||
return columnType(BLOB);
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("unknown type: " + jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerHibernateTypes() {
|
||||
|
@ -353,7 +494,9 @@ public abstract class Dialect implements ConversionContext {
|
|||
}
|
||||
}
|
||||
|
||||
public abstract DatabaseVersion getVersion();
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public JdbcType resolveSqlTypeDescriptor(
|
||||
String columnTypeName,
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
package org.hibernate.dialect;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.PessimisticLockException;
|
||||
import org.hibernate.boot.model.TypeContributions;
|
||||
|
@ -63,6 +65,7 @@ import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
|||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static org.hibernate.query.TemporalUnit.SECOND;
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
|
||||
/**
|
||||
* A dialect compatible with the H2 database.
|
||||
|
@ -77,8 +80,6 @@ public class H2Dialect extends Dialect {
|
|||
private final boolean cascadeConstraints;
|
||||
private final boolean useLocalTime;
|
||||
|
||||
private final DatabaseVersion version;
|
||||
|
||||
private final boolean supportsTuplesInSubqueries;
|
||||
private final SequenceInformationExtractor sequenceInformationExtractor;
|
||||
private final String querySequenceString;
|
||||
|
@ -88,27 +89,13 @@ public class H2Dialect extends Dialect {
|
|||
registerKeywords( info );
|
||||
}
|
||||
|
||||
private static DatabaseVersion parseVersion(DialectResolutionInfo info) {
|
||||
return DatabaseVersion.make( info.getMajor(), info.getMinor(), parseBuildId( info ) );
|
||||
}
|
||||
|
||||
private static int parseBuildId(DialectResolutionInfo info) {
|
||||
final String databaseVersion = info.getDatabaseVersion();
|
||||
if ( databaseVersion == null ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final String[] bits = databaseVersion.split("[. ]");
|
||||
return bits.length > 2 ? Integer.parseInt( bits[2] ) : 0;
|
||||
}
|
||||
|
||||
public H2Dialect() {
|
||||
this( SimpleDatabaseVersion.ZERO_VERSION );
|
||||
}
|
||||
|
||||
public H2Dialect(DatabaseVersion version) {
|
||||
super();
|
||||
this.version = version;
|
||||
super(version);
|
||||
|
||||
// https://github.com/h2database/h2database/commit/b2cdf84e0b84eb8a482fa7dccdccc1ab95241440
|
||||
limitHandler = version.isSameOrAfter( 1, 4, 195 )
|
||||
? OffsetFetchLimitHandler.INSTANCE
|
||||
|
@ -128,12 +115,6 @@ public class H2Dialect extends Dialect {
|
|||
// http://code.google.com/p/h2database/issues/detail?id=235
|
||||
getDefaultProperties().setProperty( AvailableSettings.NON_CONTEXTUAL_LOB_CREATION, "true" );
|
||||
|
||||
registerColumnType( Types.VARCHAR, "varchar" );
|
||||
registerColumnType( Types.NVARCHAR, "varchar" );
|
||||
registerColumnType( Types.VARBINARY, "varbinary" );
|
||||
|
||||
registerColumnType( SqlTypes.ARRAY, "array" );
|
||||
|
||||
if ( version.isSameOrAfter( 1, 4, 32 ) ) {
|
||||
this.sequenceInformationExtractor = version.isSameOrAfter( 1, 4, 201 )
|
||||
? SequenceInformationExtractorLegacyImpl.INSTANCE
|
||||
|
@ -151,14 +132,51 @@ public class H2Dialect extends Dialect {
|
|||
else {
|
||||
this.sequenceInformationExtractor = SequenceInformationExtractorNoOpImpl.INSTANCE;
|
||||
this.querySequenceString = null;
|
||||
if ( version.isBefore( 2 ) ) {
|
||||
// prior to version 2.0, H2 reported NUMERIC columns as DECIMAL,
|
||||
// which caused problems for schema update tool
|
||||
registerColumnType( Types.NUMERIC, "decimal($p,$s)" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static DatabaseVersion parseVersion(DialectResolutionInfo info) {
|
||||
return DatabaseVersion.make( info.getMajor(), info.getMinor(), parseBuildId( info ) );
|
||||
}
|
||||
|
||||
private static int parseBuildId(DialectResolutionInfo info) {
|
||||
final String databaseVersion = info.getDatabaseVersion();
|
||||
if ( databaseVersion == null ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final String[] bits = databaseVersion.split("[. ]");
|
||||
return bits.length > 2 ? Integer.parseInt( bits[2] ) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
if ( jdbcTypeCode == NUMERIC && getVersion().isBefore(2) ) {
|
||||
// prior to version 2.0, H2 reported NUMERIC columns as DECIMAL,
|
||||
// which caused problems for schema update tool
|
||||
return super.columnType(DECIMAL);
|
||||
}
|
||||
|
||||
switch (jdbcTypeCode) {
|
||||
case LONGVARCHAR:
|
||||
case LONGNVARCHAR:
|
||||
return "varchar";
|
||||
case LONGVARBINARY:
|
||||
return "varbinary";
|
||||
case ARRAY:
|
||||
return "array";
|
||||
default:
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getSupportedJdbcTypeCodes() {
|
||||
List<Integer> typeCodes = new ArrayList<>( super.getSupportedJdbcTypeCodes() );
|
||||
typeCodes.add(ARRAY);
|
||||
return typeCodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||
super.contributeTypes( typeContributions, serviceRegistry );
|
||||
|
@ -166,11 +184,11 @@ public class H2Dialect extends Dialect {
|
|||
final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration()
|
||||
.getJdbcTypeDescriptorRegistry();
|
||||
|
||||
if ( version.isSameOrAfter( 1, 4, 197 ) ) {
|
||||
if ( getVersion().isSameOrAfter( 1, 4, 197 ) ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||
if ( version.isSameOrAfter( 1, 4, 198 ) ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( DurationIntervalSecondJdbcType.INSTANCE );
|
||||
}
|
||||
}
|
||||
if ( getVersion().isSameOrAfter( 1, 4, 198 ) ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( DurationIntervalSecondJdbcType.INSTANCE );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,11 +197,6 @@ public class H2Dialect extends Dialect {
|
|||
return getVersion().isSame( 1, 4, 200 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
super.initializeFunctionRegistry( queryEngine );
|
||||
|
@ -235,7 +248,7 @@ public class H2Dialect extends Dialect {
|
|||
CommonFunctionFactory.median( queryEngine );
|
||||
CommonFunctionFactory.stddevPopSamp( queryEngine );
|
||||
CommonFunctionFactory.varPopSamp( queryEngine );
|
||||
if ( version.isSame( 1, 4, 200 ) ) {
|
||||
if ( getVersion().isSame( 1, 4, 200 ) ) {
|
||||
// See https://github.com/h2database/h2database/issues/2518
|
||||
CommonFunctionFactory.format_toChar( queryEngine );
|
||||
}
|
||||
|
@ -524,7 +537,7 @@ public class H2Dialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public void appendDatetimeFormat(SqlAppender appender, String format) {
|
||||
if ( version.isSame( 1, 4, 200 ) ) {
|
||||
if ( getVersion().isSame( 1, 4, 200 ) ) {
|
||||
// See https://github.com/h2database/h2database/issues/2518
|
||||
appender.appendSql( OracleDialect.datetimeFormat( format, true, true ).result() );
|
||||
}
|
||||
|
|
|
@ -71,6 +71,10 @@ import org.jboss.logging.Logger;
|
|||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
||||
import static org.hibernate.type.SqlTypes.BLOB;
|
||||
import static org.hibernate.type.SqlTypes.CLOB;
|
||||
import static org.hibernate.type.SqlTypes.NCLOB;
|
||||
import static org.hibernate.type.SqlTypes.NUMERIC;
|
||||
|
||||
/**
|
||||
* An SQL dialect compatible with HyperSQL (HSQLDB) version 1.8 and above.
|
||||
|
@ -85,11 +89,6 @@ public class HSQLDialect extends Dialect {
|
|||
HSQLDialect.class.getName()
|
||||
);
|
||||
|
||||
/**
|
||||
* version is 180 for 1.8.0 or 200 for 2.0.0
|
||||
*/
|
||||
private final DatabaseVersion version;
|
||||
|
||||
public HSQLDialect(DialectResolutionInfo info) {
|
||||
this( info.makeCopy() );
|
||||
registerKeywords( info );
|
||||
|
@ -100,41 +99,48 @@ public class HSQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
public HSQLDialect(DatabaseVersion version) {
|
||||
super();
|
||||
super( version.isSame( 1, 8 ) ? reflectedVersion( version ) : version );
|
||||
|
||||
if ( version.isSame( 1, 8 ) ) {
|
||||
version = reflectedVersion( version );
|
||||
}
|
||||
|
||||
this.version = version;
|
||||
|
||||
//Note that all floating point types are synonyms for 'double'
|
||||
|
||||
//Note that the HSQL type 'longvarchar' and 'longvarbinary'
|
||||
//are synonyms for 'varchar(16M)' and 'varbinary(16M)' respectively.
|
||||
//Using these types though results in schema validation issue like described in HHH-9693
|
||||
|
||||
//HSQL has no 'nclob' type, but 'clob' is Unicode
|
||||
//(See HHH-10364)
|
||||
registerColumnType( Types.NCLOB, "clob" );
|
||||
|
||||
if ( this.version.isBefore( 2 ) ) {
|
||||
//Older versions of HSQL did not accept
|
||||
//precision for the 'numeric' type
|
||||
registerColumnType( Types.NUMERIC, "numeric" );
|
||||
|
||||
//Older versions of HSQL had no lob support
|
||||
registerColumnType( Types.BLOB, "longvarbinary" );
|
||||
registerColumnType( Types.CLOB, "longvarchar" );
|
||||
}
|
||||
|
||||
if ( this.version.isSameOrAfter( 2, 5 ) ) {
|
||||
if ( getVersion().isSameOrAfter( 2, 5 ) ) {
|
||||
registerKeyword( "period" );
|
||||
}
|
||||
|
||||
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
// Note that all floating point types are synonyms for 'double'
|
||||
|
||||
// Note that the HSQL type 'longvarchar' and 'longvarbinary' are
|
||||
// synonyms for 'varchar(16M)' and 'varbinary(16M)' respectively.
|
||||
// But using these types results in schema validation issue as
|
||||
// described in HHH-9693.
|
||||
|
||||
//HSQL has no 'nclob' type, but 'clob' is Unicode (See HHH-10364)
|
||||
if ( jdbcTypeCode==NCLOB ) {
|
||||
jdbcTypeCode = CLOB;
|
||||
}
|
||||
|
||||
if ( getVersion().isBefore( 2 ) ) {
|
||||
switch (jdbcTypeCode) {
|
||||
case NUMERIC:
|
||||
// Older versions of HSQL did not accept
|
||||
// precision for the 'numeric' type
|
||||
return "numeric";
|
||||
|
||||
// Older versions of HSQL had no lob support
|
||||
case BLOB:
|
||||
return "longvarbinary";
|
||||
case CLOB:
|
||||
return "longvarchar";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
|
||||
private static DatabaseVersion reflectedVersion(DatabaseVersion version) {
|
||||
try {
|
||||
final Class<?> props = ReflectHelper.classForName("org.hsqldb.persist.HsqlDatabaseProperties");
|
||||
|
@ -152,11 +158,6 @@ public class HSQLDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
super.initializeFunctionRegistry( queryEngine );
|
||||
|
@ -208,13 +209,13 @@ public class HSQLDialect extends Dialect {
|
|||
CommonFunctionFactory.addMonths( queryEngine );
|
||||
CommonFunctionFactory.monthsBetween( queryEngine );
|
||||
|
||||
if ( version.isSameOrAfter( 2 ) ) {
|
||||
if ( getVersion().isSameOrAfter( 2 ) ) {
|
||||
//SYSDATE is similar to LOCALTIMESTAMP but it returns the timestamp when it is called
|
||||
CommonFunctionFactory.sysdate( queryEngine );
|
||||
}
|
||||
|
||||
// from v. 2.2.0 ROWNUM() is supported in all modes as the equivalent of Oracle ROWNUM
|
||||
if ( version.isSameOrAfter( 2, 2 ) ) {
|
||||
if ( getVersion().isSameOrAfter( 2, 2 ) ) {
|
||||
CommonFunctionFactory.rownum( queryEngine );
|
||||
}
|
||||
}
|
||||
|
@ -357,7 +358,7 @@ public class HSQLDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public String getForUpdateString() {
|
||||
if ( version.isSameOrAfter( 2 ) ) {
|
||||
if ( getVersion().isSameOrAfter( 2 ) ) {
|
||||
return " for update";
|
||||
}
|
||||
else {
|
||||
|
@ -367,8 +368,8 @@ public class HSQLDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public LimitHandler getLimitHandler() {
|
||||
return version.isBefore( 2 ) ? LegacyHSQLLimitHandler.INSTANCE
|
||||
: version.isBefore( 2, 5 ) ? LimitOffsetLimitHandler.INSTANCE
|
||||
return getVersion().isBefore( 2 ) ? LegacyHSQLLimitHandler.INSTANCE
|
||||
: getVersion().isBefore( 2, 5 ) ? LimitOffsetLimitHandler.INSTANCE
|
||||
: OffsetFetchLimitHandler.INSTANCE;
|
||||
}
|
||||
|
||||
|
@ -387,7 +388,7 @@ public class HSQLDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public boolean supportsColumnCheck() {
|
||||
return version.isSameOrAfter( 2 );
|
||||
return getVersion().isSameOrAfter( 2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -408,7 +409,7 @@ public class HSQLDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() {
|
||||
return version.isBefore( 2 ) ? EXTRACTOR_18 : EXTRACTOR_20;
|
||||
return getVersion().isBefore( 2 ) ? EXTRACTOR_18 : EXTRACTOR_20;
|
||||
}
|
||||
|
||||
private static final ViolatedConstraintNameExtractor EXTRACTOR_18 =
|
||||
|
@ -518,7 +519,7 @@ public class HSQLDialect extends Dialect {
|
|||
// the definition and data is private to the session and table declaration
|
||||
// can happen in the middle of a transaction
|
||||
|
||||
if ( version.isBefore( 2 ) ) {
|
||||
if ( getVersion().isBefore( 2 ) ) {
|
||||
return new GlobalTemporaryTableMutationStrategy(
|
||||
TemporaryTable.createIdTable(
|
||||
rootEntityDescriptor,
|
||||
|
@ -558,7 +559,7 @@ public class HSQLDialect extends Dialect {
|
|||
// the definition and data is private to the session and table declaration
|
||||
// can happen in the middle of a transaction
|
||||
|
||||
if ( version.isBefore( 2 ) ) {
|
||||
if ( getVersion().isBefore( 2 ) ) {
|
||||
return new GlobalTemporaryTableInsertStrategy(
|
||||
TemporaryTable.createEntityTable(
|
||||
rootEntityDescriptor,
|
||||
|
@ -586,24 +587,24 @@ public class HSQLDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public TemporaryTableKind getSupportedTemporaryTableKind() {
|
||||
return version.isBefore( 2 ) ? TemporaryTableKind.GLOBAL : TemporaryTableKind.LOCAL;
|
||||
return getVersion().isBefore( 2 ) ? TemporaryTableKind.GLOBAL : TemporaryTableKind.LOCAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemporaryTableCreateCommand() {
|
||||
return version.isBefore( 2 ) ? super.getTemporaryTableCreateCommand() : "declare local temporary table";
|
||||
return getVersion().isBefore( 2 ) ? super.getTemporaryTableCreateCommand() : "declare local temporary table";
|
||||
}
|
||||
|
||||
@Override
|
||||
public AfterUseAction getTemporaryTableAfterUseAction() {
|
||||
// Version 1.8 GLOBAL TEMPORARY table definitions persist beyond the end
|
||||
// of the session (by default, data is cleared at commit).
|
||||
return version.isBefore( 2 ) ? AfterUseAction.CLEAN : AfterUseAction.DROP;
|
||||
return getVersion().isBefore( 2 ) ? AfterUseAction.CLEAN : AfterUseAction.DROP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeforeUseAction getTemporaryTableBeforeUseAction() {
|
||||
return version.isBefore( 2 ) ? BeforeUseAction.NONE : BeforeUseAction.CREATE;
|
||||
return getVersion().isBefore( 2 ) ? BeforeUseAction.NONE : BeforeUseAction.CREATE;
|
||||
}
|
||||
|
||||
// current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -651,7 +652,7 @@ public class HSQLDialect extends Dialect {
|
|||
case OPTIMISTIC_FORCE_INCREMENT:
|
||||
return new OptimisticForceIncrementLockingStrategy(lockable, lockMode);
|
||||
}
|
||||
if ( version.isBefore( 2 ) ) {
|
||||
if ( getVersion().isBefore( 2 ) ) {
|
||||
return new ReadUncommittedLockingStrategy( lockable, lockMode );
|
||||
}
|
||||
else {
|
||||
|
@ -676,19 +677,19 @@ public class HSQLDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public boolean supportsCommentOn() {
|
||||
return version.isSameOrAfter( 2 );
|
||||
return getVersion().isSameOrAfter( 2 );
|
||||
}
|
||||
|
||||
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
public boolean doesReadCommittedCauseWritersToBlockReaders() {
|
||||
return version.isSameOrAfter( 2 );
|
||||
return getVersion().isSameOrAfter( 2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesRepeatableReadCauseReadersToBlockWriters() {
|
||||
return version.isSameOrAfter( 2 );
|
||||
return getVersion().isSameOrAfter( 2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -709,7 +710,7 @@ public class HSQLDialect extends Dialect {
|
|||
@Override
|
||||
public boolean supportsTupleDistinctCounts() {
|
||||
// from v. 2.2.9 is added support for COUNT(DISTINCT ...) with multiple arguments
|
||||
return version.isSameOrAfter( 2, 2, 9 );
|
||||
return getVersion().isSameOrAfter( 2, 2, 9 );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -724,7 +725,7 @@ public class HSQLDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public IdentityColumnSupport getIdentityColumnSupport() {
|
||||
return new HSQLIdentityColumnSupport( this.version );
|
||||
return new HSQLIdentityColumnSupport( this.getVersion() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,35 +34,34 @@ import org.hibernate.type.StandardBasicTypes;
|
|||
*/
|
||||
public class MariaDBDialect extends MySQLDialect {
|
||||
|
||||
private final DatabaseVersion version;
|
||||
private final DatabaseVersion mariaVersion;
|
||||
|
||||
public MariaDBDialect() {
|
||||
this( DatabaseVersion.make( 5 ) );
|
||||
}
|
||||
|
||||
public MariaDBDialect(DialectResolutionInfo info) {
|
||||
this( info.makeCopy(), getCharacterSetBytesPerCharacter( info.unwrap( DatabaseMetaData.class ) ) );
|
||||
this( info.makeCopy(), info );
|
||||
registerKeywords( info );
|
||||
}
|
||||
|
||||
public MariaDBDialect(DatabaseVersion version) {
|
||||
// Let's be conservative and assume people use a 4 byte character set
|
||||
this( version, 4 );
|
||||
this(version, null);
|
||||
}
|
||||
|
||||
public MariaDBDialect(DatabaseVersion version, int characterSetBytesPerCharacter) {
|
||||
protected MariaDBDialect(DatabaseVersion mariaVersion, DialectResolutionInfo info) {
|
||||
super(
|
||||
version.isBefore( 5, 3 )
|
||||
mariaVersion.isBefore( 5, 3 )
|
||||
? DatabaseVersion.make( 5 )
|
||||
: DatabaseVersion.make( 5, 7 ),
|
||||
characterSetBytesPerCharacter
|
||||
info
|
||||
);
|
||||
this.version = version;
|
||||
this.mariaVersion = mariaVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
return mariaVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,6 +11,8 @@ import java.sql.DatabaseMetaData;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
|
@ -76,6 +78,7 @@ import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
|||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
|
||||
/**
|
||||
* An SQL dialect for MySQL (prior to 5.x).
|
||||
|
@ -86,12 +89,12 @@ public class MySQLDialect extends Dialect {
|
|||
|
||||
private final UniqueDelegate uniqueDelegate;
|
||||
private final MySQLStorageEngine storageEngine;
|
||||
private final DatabaseVersion version;
|
||||
private final int characterSetBytesPerCharacter;
|
||||
private final SizeStrategy sizeStrategy;
|
||||
private int maxVarcharLength;
|
||||
private int maxVarbinaryLength;
|
||||
|
||||
public MySQLDialect(DialectResolutionInfo info) {
|
||||
this( info.makeCopy(), getCharacterSetBytesPerCharacter( info.unwrap( DatabaseMetaData.class ) ) );
|
||||
this( info.makeCopy(), info );
|
||||
registerKeywords( info );
|
||||
}
|
||||
|
||||
|
@ -100,16 +103,11 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
public MySQLDialect(DatabaseVersion version) {
|
||||
// Let's be conservative and assume people use a 4 byte character set
|
||||
this( version, 4 );
|
||||
this(version, null);
|
||||
}
|
||||
|
||||
public MySQLDialect(DatabaseVersion version, int characterSetBytesPerCharacter) {
|
||||
super(false);
|
||||
this.version = version;
|
||||
this.characterSetBytesPerCharacter = characterSetBytesPerCharacter;
|
||||
|
||||
registerDefaultColumnTypes();
|
||||
protected MySQLDialect(DatabaseVersion mySQLVersion, DialectResolutionInfo info) {
|
||||
super(mySQLVersion, info);
|
||||
|
||||
String storageEngine = Environment.getProperties().getProperty( Environment.STORAGE_ENGINE );
|
||||
if (storageEngine == null) {
|
||||
|
@ -128,72 +126,13 @@ public class MySQLDialect extends Dialect {
|
|||
throw new UnsupportedOperationException( "The " + storageEngine + " storage engine is not supported!" );
|
||||
}
|
||||
|
||||
registerColumnType( Types.BOOLEAN, "bit" ); // HHH-6935: Don't use "boolean" i.e. tinyint(1) due to JDBC ResultSetMetaData
|
||||
|
||||
registerColumnType( Types.NUMERIC, "decimal($p,$s)" ); //it's just a synonym
|
||||
|
||||
if ( getMySQLVersion().isBefore( 5, 7 ) ) {
|
||||
registerColumnType( Types.TIMESTAMP, "datetime" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp" );
|
||||
}
|
||||
else {
|
||||
// Since 5.7 we can explicitly specify a fractional second
|
||||
// precision for the timestamp-like types
|
||||
registerColumnType(Types.TIMESTAMP, "datetime($p)");
|
||||
registerColumnType(Types.TIMESTAMP_WITH_TIMEZONE, "timestamp($p)");
|
||||
}
|
||||
|
||||
final int maxTinyLobLen = 255;
|
||||
final int maxLobLen = 65_535;
|
||||
final int maxMediumLobLen = 16_777_215;
|
||||
//the maximum long LOB length is 4_294_967_295, bigger than any Java string
|
||||
|
||||
registerColumnType( Types.VARCHAR, "longtext" );
|
||||
registerColumnType( Types.VARCHAR, maxMediumLobLen, "mediumtext" );
|
||||
if ( getMaxVarcharLength() < maxLobLen ) {
|
||||
registerColumnType( Types.VARCHAR, maxLobLen, "text" );
|
||||
}
|
||||
|
||||
registerColumnType( Types.NVARCHAR, "longtext" );
|
||||
registerColumnType( Types.NVARCHAR, maxMediumLobLen, "mediumtext" );
|
||||
if ( getMaxNVarcharLength() < maxLobLen ) {
|
||||
registerColumnType( Types.NVARCHAR, maxLobLen, "text" );
|
||||
}
|
||||
|
||||
registerColumnType( Types.VARBINARY, "longblob" );
|
||||
registerColumnType( Types.VARBINARY, maxMediumLobLen, "mediumblob" );
|
||||
if ( getMaxVarbinaryLength() < maxLobLen ) {
|
||||
registerColumnType( Types.VARBINARY, maxLobLen, "blob" );
|
||||
}
|
||||
|
||||
registerColumnType( Types.BLOB, "longblob" );
|
||||
registerColumnType( Types.BLOB, maxMediumLobLen, "mediumblob" );
|
||||
registerColumnType( Types.BLOB, maxLobLen, "blob" );
|
||||
registerColumnType( Types.BLOB, maxTinyLobLen, "tinyblob" );
|
||||
|
||||
registerColumnType( Types.CLOB, "longtext" );
|
||||
registerColumnType( Types.CLOB, maxMediumLobLen, "mediumtext" );
|
||||
registerColumnType( Types.CLOB, maxLobLen, "text" );
|
||||
registerColumnType( Types.CLOB, maxTinyLobLen, "tinytext" );
|
||||
|
||||
registerColumnType( Types.NCLOB, "longtext" );
|
||||
registerColumnType( Types.NCLOB, maxMediumLobLen, "mediumtext" );
|
||||
registerColumnType( Types.NCLOB, maxLobLen, "text" );
|
||||
registerColumnType( Types.NCLOB, maxTinyLobLen, "tinytext" );
|
||||
|
||||
if ( getMySQLVersion().isBefore( 5, 7 ) ) {
|
||||
// MySQL 5.7 brings JSON native support with a dedicated datatype
|
||||
// https://dev.mysql.com/doc/refman/5.7/en/json.html
|
||||
registerColumnType( SqlTypes.JSON, "json");
|
||||
}
|
||||
registerColumnType( SqlTypes.GEOMETRY, "geometry" );
|
||||
|
||||
registerKeyword( "key" );
|
||||
|
||||
getDefaultProperties().setProperty( Environment.MAX_FETCH_DEPTH, "2" );
|
||||
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
|
||||
|
||||
uniqueDelegate = new MySQLUniqueDelegate( this );
|
||||
|
||||
sizeStrategy = new SizeStrategyImpl() {
|
||||
@Override
|
||||
public Size resolveSize(
|
||||
|
@ -204,7 +143,7 @@ public class MySQLDialect extends Dialect {
|
|||
Long length) {
|
||||
switch ( jdbcType.getDefaultSqlTypeCode() ) {
|
||||
case Types.BIT:
|
||||
// MySQL allows BIT with a length up to 64
|
||||
// MySQL allows BIT with a length up to 64 (less the the default length 255)
|
||||
if ( length != null ) {
|
||||
return Size.length( Math.min( Math.max( length, 1 ), 64 ) );
|
||||
}
|
||||
|
@ -214,6 +153,101 @@ public class MySQLDialect extends Dialect {
|
|||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getSupportedJdbcTypeCodes() {
|
||||
List<Integer> typeCodes = new ArrayList<>( super.getSupportedJdbcTypeCodes() );
|
||||
typeCodes.add(GEOMETRY);
|
||||
if ( getMySQLVersion().isBefore( 5, 7 ) ) {
|
||||
// MySQL 5.7 brings JSON native support with a dedicated datatype
|
||||
// https://dev.mysql.com/doc/refman/5.7/en/json.html
|
||||
typeCodes.add(JSON);
|
||||
}
|
||||
return typeCodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
switch (jdbcTypeCode) {
|
||||
case BOOLEAN:
|
||||
// HHH-6935: Don't use "boolean" i.e. tinyint(1) due to JDBC ResultSetMetaData
|
||||
return "bit";
|
||||
|
||||
case TIMESTAMP:
|
||||
return getMySQLVersion().isBefore( 5, 7 )
|
||||
? "datetime" : "datetime($p)";
|
||||
case TIMESTAMP_WITH_TIMEZONE:
|
||||
return getMySQLVersion().isBefore( 5, 7 )
|
||||
? "timestamp" : "timestamp($p)";
|
||||
|
||||
case NUMERIC:
|
||||
// it's just a synonym
|
||||
return super.columnType(DECIMAL);
|
||||
|
||||
case JSON:
|
||||
return "json";
|
||||
case GEOMETRY:
|
||||
return "geometry";
|
||||
|
||||
case BLOB:
|
||||
return "longblob";
|
||||
case NCLOB:
|
||||
case CLOB:
|
||||
return "longtext";
|
||||
}
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerDefaultColumnTypes(DialectResolutionInfo info) {
|
||||
// we need to remember the character set before calling getMaxVarcharLength()
|
||||
// we could not do this earlier because we get called from the constructor
|
||||
// of the superclass, before our own constructor has run
|
||||
int bytesPerCharacter = info == null
|
||||
? 4 // Let's be conservative and assume people use a 4 byte character set
|
||||
: getCharacterSetBytesPerCharacter( info.unwrap(DatabaseMetaData.class) );
|
||||
maxVarcharLength = maxVarcharLength(bytesPerCharacter);
|
||||
maxVarbinaryLength = maxVarbinaryLength();
|
||||
|
||||
super.registerDefaultColumnTypes( maxVarcharLength, maxVarcharLength, maxVarbinaryLength );
|
||||
|
||||
// MySQL has approximately one million text and blob types. We have
|
||||
// already registered longtext + longblob via the regular method,
|
||||
// but we still need to do the rest of them here.
|
||||
|
||||
final int maxTinyLobLen = 255;
|
||||
final int maxLobLen = 65_535;
|
||||
final int maxMediumLobLen = 16_777_215;
|
||||
|
||||
//the maximum long LOB length is 4_294_967_295, bigger than any Java string
|
||||
|
||||
registerColumnType( VARCHAR, maxMediumLobLen, "mediumtext" );
|
||||
if ( getMaxVarcharLength() < maxLobLen ) {
|
||||
registerColumnType( VARCHAR, maxLobLen, "text" );
|
||||
}
|
||||
|
||||
registerColumnType( NVARCHAR, maxMediumLobLen, "mediumtext" );
|
||||
if ( getMaxNVarcharLength() < maxLobLen ) {
|
||||
registerColumnType( NVARCHAR, maxLobLen, "text" );
|
||||
}
|
||||
|
||||
registerColumnType( VARBINARY, maxMediumLobLen, "mediumblob" );
|
||||
if ( getMaxVarbinaryLength() < maxLobLen ) {
|
||||
registerColumnType( VARBINARY, maxLobLen, "blob" );
|
||||
}
|
||||
|
||||
registerColumnType( BLOB, maxMediumLobLen, "mediumblob" );
|
||||
registerColumnType( BLOB, maxLobLen, "blob" );
|
||||
registerColumnType( BLOB, maxTinyLobLen, "tinyblob" );
|
||||
|
||||
registerColumnType( CLOB, maxMediumLobLen, "mediumtext" );
|
||||
registerColumnType( CLOB, maxLobLen, "text" );
|
||||
registerColumnType( CLOB, maxTinyLobLen, "tinytext" );
|
||||
|
||||
registerColumnType( NCLOB, maxMediumLobLen, "mediumtext" );
|
||||
registerColumnType( NCLOB, maxLobLen, "text" );
|
||||
registerColumnType( NCLOB, maxTinyLobLen, "tinytext" );
|
||||
}
|
||||
|
||||
protected static int getCharacterSetBytesPerCharacter(DatabaseMetaData databaseMetaData) {
|
||||
if ( databaseMetaData != null ) {
|
||||
try (java.sql.Statement s = databaseMetaData.getConnection().createStatement() ) {
|
||||
|
@ -254,14 +288,17 @@ public class MySQLDialect extends Dialect {
|
|||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarcharLength() {
|
||||
private int maxVarbinaryLength() {
|
||||
return getMySQLVersion().isBefore( 5 ) ? 255 : 65_535;
|
||||
}
|
||||
|
||||
private int maxVarcharLength(int bytesPerCharacter) {
|
||||
// max length for VARCHAR changed in 5.0.3
|
||||
if ( getMySQLVersion().isBefore( 5 ) ) {
|
||||
return 255;
|
||||
}
|
||||
else {
|
||||
switch ( characterSetBytesPerCharacter ) {
|
||||
switch ( bytesPerCharacter ) {
|
||||
case 1:
|
||||
return 65_535;
|
||||
case 2:
|
||||
|
@ -275,9 +312,14 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarcharLength() {
|
||||
return maxVarcharLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarbinaryLength() {
|
||||
return getMySQLVersion().isBefore( 5 ) ? 255 : 65_535;
|
||||
return maxVarbinaryLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -290,13 +332,8 @@ public class MySQLDialect extends Dialect {
|
|||
return super.getNullColumnString( columnType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public DatabaseVersion getMySQLVersion() {
|
||||
return version;
|
||||
return super.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,8 @@ import java.sql.CallableStatement;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -68,7 +70,6 @@ import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOr
|
|||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.NullType;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
|
||||
|
@ -86,6 +87,7 @@ import static org.hibernate.query.TemporalUnit.MINUTE;
|
|||
import static org.hibernate.query.TemporalUnit.MONTH;
|
||||
import static org.hibernate.query.TemporalUnit.SECOND;
|
||||
import static org.hibernate.query.TemporalUnit.YEAR;
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
|
||||
/**
|
||||
* A dialect for Oracle 8i and above.
|
||||
|
@ -105,7 +107,6 @@ public class OracleDialect extends Dialect {
|
|||
public static final String PREFER_LONG_RAW = "hibernate.dialect.oracle.prefer_long_raw";
|
||||
|
||||
private final LimitHandler limitHandler;
|
||||
private final DatabaseVersion version;
|
||||
|
||||
public OracleDialect(DialectResolutionInfo info) {
|
||||
this( info.makeCopy() );
|
||||
|
@ -117,15 +118,8 @@ public class OracleDialect extends Dialect {
|
|||
}
|
||||
|
||||
public OracleDialect(DatabaseVersion version) {
|
||||
super();
|
||||
this.version = version;
|
||||
super(version);
|
||||
|
||||
registerCharacterTypeMappings();
|
||||
registerNumericTypeMappings();
|
||||
registerDateTimeTypeMappings();
|
||||
registerBinaryTypeMappings();
|
||||
registerExtendedTypeMappings();
|
||||
registerReverseHibernateTypeMappings();
|
||||
registerDefaultProperties();
|
||||
|
||||
limitHandler = supportsFetchClause( FetchClauseType.ROWS_ONLY )
|
||||
|
@ -133,11 +127,6 @@ public class OracleDialect extends Dialect {
|
|||
: new LegacyOracleLimitHandler( getVersion() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferredSqlTypeCodeForBoolean() {
|
||||
return Types.BIT;
|
||||
|
@ -536,52 +525,69 @@ public class OracleDialect extends Dialect {
|
|||
pattern.append( unit.conversionFactor( toUnit, this ) );
|
||||
}
|
||||
|
||||
protected void registerCharacterTypeMappings() {
|
||||
if ( getVersion().isBefore( 9 ) ) {
|
||||
registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "varchar2($l)" );
|
||||
registerColumnType( Types.VARCHAR, "clob" );
|
||||
}
|
||||
else {
|
||||
registerColumnType( Types.CHAR, "char($l char)" );
|
||||
registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "varchar2($l char)" );
|
||||
registerColumnType( Types.VARCHAR, "clob" );
|
||||
registerColumnType( Types.NVARCHAR, getMaxNVarcharLength(), "nvarchar2($l)" );
|
||||
registerColumnType( Types.NVARCHAR, "nclob" );
|
||||
}
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
//note: the 'long' type is deprecated
|
||||
switch (jdbcTypeCode) {
|
||||
case BOOLEAN:
|
||||
// still, after all these years...
|
||||
return "number(1,0)";
|
||||
|
||||
case VARCHAR:
|
||||
return getVersion().isBefore( 9 )
|
||||
? "varchar2($l)": "varchar2($l char)";
|
||||
case NVARCHAR:
|
||||
return "nvarchar2($l)";
|
||||
|
||||
case BIGINT:
|
||||
return "number(19,0)";
|
||||
case SMALLINT:
|
||||
return "number(5,0)";
|
||||
case TINYINT:
|
||||
return "number(3,0)";
|
||||
case INTEGER:
|
||||
return "number(10,0)";
|
||||
|
||||
case REAL:
|
||||
// Oracle's 'real' type is actually double precision
|
||||
return "float(24)";
|
||||
|
||||
case NUMERIC:
|
||||
case DECIMAL:
|
||||
// Note that 38 is the maximum precision Oracle supports
|
||||
return "number($p,$s)";
|
||||
|
||||
case DATE:
|
||||
case TIME:
|
||||
return "date";
|
||||
case TIMESTAMP:
|
||||
// the only difference between date and timestamp
|
||||
// on Oracle is that date has no fractional seconds
|
||||
return getVersion().isBefore( 9 )
|
||||
? "date" : "timestamp($p)";
|
||||
case TIME_WITH_TIMEZONE:
|
||||
return getVersion().isBefore( 9 )
|
||||
? "date" : "timestamp($p) with time zone";
|
||||
|
||||
case BINARY:
|
||||
case VARBINARY:
|
||||
return "raw($l)";
|
||||
|
||||
case GEOMETRY:
|
||||
return "MDSYS.SDO_GEOMETRY";
|
||||
|
||||
default:
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerNumericTypeMappings() {
|
||||
registerColumnType( Types.BOOLEAN, "number(1,0)" );
|
||||
|
||||
registerColumnType( Types.BIGINT, "number(19,0)" );
|
||||
registerColumnType( Types.SMALLINT, "number(5,0)" );
|
||||
registerColumnType( Types.TINYINT, "number(3,0)" );
|
||||
registerColumnType( Types.INTEGER, "number(10,0)" );
|
||||
|
||||
// Oracle has DOUBLE semantics for the REAL type, so we map it to float(24)
|
||||
registerColumnType( Types.REAL, "float(24)" );
|
||||
|
||||
// Note that 38 is the maximum precision Oracle supports
|
||||
registerColumnType( Types.NUMERIC, "number($p,$s)" );
|
||||
registerColumnType( Types.DECIMAL, "number($p,$s)" );
|
||||
}
|
||||
|
||||
protected void registerDateTimeTypeMappings() {
|
||||
if ( getVersion().isBefore( 9 ) ) {
|
||||
registerColumnType( Types.DATE, "date" );
|
||||
registerColumnType( Types.TIME, "date" );
|
||||
registerColumnType( Types.TIMESTAMP, "date" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "date" );
|
||||
}
|
||||
else {
|
||||
//the only difference between date and timestamp
|
||||
//on Oracle is that date has no fractional seconds
|
||||
registerColumnType( Types.DATE, "date" );
|
||||
registerColumnType( Types.TIME, "date" );
|
||||
registerColumnType( Types.TIMESTAMP, "timestamp($p)" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp($p) with time zone" );
|
||||
@Override
|
||||
protected List<Integer> getSupportedJdbcTypeCodes() {
|
||||
List<Integer> list = new ArrayList<>( super.getSupportedJdbcTypeCodes() );
|
||||
if ( getVersion().isSameOrAfter( 10 ) ) {
|
||||
list.add(GEOMETRY);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -589,23 +595,6 @@ public class OracleDialect extends Dialect {
|
|||
return getVersion().isSameOrAfter( 9 ) ? TimeZoneSupport.NATIVE : TimeZoneSupport.NONE;
|
||||
}
|
||||
|
||||
protected void registerBinaryTypeMappings() {
|
||||
registerColumnType( Types.BINARY, getMaxVarbinaryLength(), "raw($l)" );
|
||||
registerColumnType( Types.BINARY, "blob" );
|
||||
|
||||
registerColumnType( Types.VARBINARY, getMaxVarbinaryLength(), "raw($l)" );
|
||||
registerColumnType( Types.VARBINARY, "blob" );
|
||||
}
|
||||
|
||||
protected void registerExtendedTypeMappings() {
|
||||
if ( getVersion().isSameOrAfter( 10 ) ) {
|
||||
registerColumnType( SqlTypes.GEOMETRY, "MDSYS.SDO_GEOMETRY" );
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerReverseHibernateTypeMappings() {
|
||||
}
|
||||
|
||||
protected void registerDefaultProperties() {
|
||||
getDefaultProperties().setProperty( Environment.USE_STREAMS_FOR_BINARY, "true" );
|
||||
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
|
@ -85,6 +86,7 @@ import static org.hibernate.query.TemporalUnit.EPOCH;
|
|||
import static org.hibernate.query.TemporalUnit.MONTH;
|
||||
import static org.hibernate.query.TemporalUnit.QUARTER;
|
||||
import static org.hibernate.query.TemporalUnit.YEAR;
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros;
|
||||
|
@ -98,7 +100,6 @@ public class PostgreSQLDialect extends Dialect {
|
|||
|
||||
private static final PostgreSQLIdentityColumnSupport IDENTITY_COLUMN_SUPPORT = new PostgreSQLIdentityColumnSupport();
|
||||
|
||||
private final DatabaseVersion version;
|
||||
private final PostgreSQLDriverKind driverKind;
|
||||
|
||||
public PostgreSQLDialect(DialectResolutionInfo info) {
|
||||
|
@ -116,53 +117,77 @@ public class PostgreSQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
public PostgreSQLDialect(DatabaseVersion version, PostgreSQLDriverKind driverKind) {
|
||||
super();
|
||||
this.version = version;
|
||||
super(version);
|
||||
this.driverKind = driverKind;
|
||||
|
||||
registerColumnType( Types.TINYINT, "smallint" ); //no tinyint, not even in Postgres 11
|
||||
|
||||
registerColumnType( Types.VARBINARY, "bytea" );
|
||||
registerColumnType( Types.BINARY, "bytea" );
|
||||
|
||||
//use oid as the blob type on Postgres because
|
||||
//the JDBC driver is rubbish
|
||||
registerColumnType( Types.BLOB, "oid" );
|
||||
registerColumnType( Types.CLOB, "oid" );
|
||||
|
||||
//there are no nchar/nvarchar types in Postgres
|
||||
registerColumnType( Types.NCHAR, "char($l)" );
|
||||
registerColumnType( Types.NVARCHAR, getMaxNVarcharLength(), "varchar($l)" );
|
||||
registerColumnType( Types.NVARCHAR, "text" );
|
||||
|
||||
// since there's no real difference between TEXT and VARCHAR,
|
||||
// except for the length limit, we can just use 'text' for the
|
||||
// "long" string types
|
||||
registerColumnType( Types.VARCHAR, "text" );
|
||||
|
||||
registerColumnType( SqlTypes.INET, "inet" );
|
||||
registerColumnType( SqlTypes.INTERVAL_SECOND, "interval second($s)" );
|
||||
|
||||
if ( getVersion().isSameOrAfter( 8, 2 ) ) {
|
||||
registerColumnType( SqlTypes.UUID, "uuid" );
|
||||
|
||||
if ( getVersion().isSameOrAfter( 9, 2 ) ) {
|
||||
// Prefer jsonb if possible
|
||||
if ( getVersion().isSameOrAfter( 9, 4 ) ) {
|
||||
registerColumnType( SqlTypes.JSON, "jsonb" );
|
||||
}
|
||||
else {
|
||||
registerColumnType( SqlTypes.JSON, "json" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerColumnType( SqlTypes.GEOMETRY, "geometry" );
|
||||
|
||||
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
|
||||
getDefaultProperties().setProperty( Environment.NON_CONTEXTUAL_LOB_CREATION, "true" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
switch (jdbcTypeCode) {
|
||||
case TINYINT:
|
||||
// no tinyint, not even in Postgres 11
|
||||
return "smallint";
|
||||
|
||||
case BINARY:
|
||||
return "bytea";
|
||||
|
||||
case BLOB:
|
||||
case CLOB:
|
||||
// use oid as the blob type on Postgres because
|
||||
// the JDBC driver is rubbish
|
||||
return "oid";
|
||||
|
||||
// there are no nchar/nvarchar types in Postgres
|
||||
case NCHAR:
|
||||
return super.columnType(CHAR);
|
||||
case NVARCHAR:
|
||||
return super.columnType(VARCHAR);
|
||||
|
||||
// since there's no real difference between TEXT and VARCHAR,
|
||||
// except for the length limit, we can just use 'text' for the
|
||||
// "long" string types
|
||||
case LONGVARCHAR:
|
||||
case LONGNVARCHAR:
|
||||
return "text";
|
||||
// use bytea as the "long" binary type (that there is no
|
||||
// real VARBINARY type in Postgres, so we always use this)
|
||||
case LONGVARBINARY:
|
||||
return "bytea";
|
||||
|
||||
case INET:
|
||||
return "inet";
|
||||
case UUID:
|
||||
return "uuid";
|
||||
case GEOMETRY:
|
||||
return "geometry";
|
||||
case JSON:
|
||||
// Prefer jsonb if possible
|
||||
return getVersion().isSameOrAfter( 9, 4 )
|
||||
? "jsonb" : "json";
|
||||
case INTERVAL_SECOND:
|
||||
return "interval second($s)";
|
||||
|
||||
default:
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getSupportedJdbcTypeCodes() {
|
||||
List<Integer> typeCodes = new ArrayList<>( super.getSupportedJdbcTypeCodes() );
|
||||
typeCodes.addAll( List.of(INET, INTERVAL_SECOND, GEOMETRY) );
|
||||
if ( getVersion().isSameOrAfter( 8, 2 ) ) {
|
||||
typeCodes.add(UUID);
|
||||
}
|
||||
if ( getVersion().isSameOrAfter( 9, 2 ) ) {
|
||||
typeCodes.add(JSON);
|
||||
}
|
||||
return typeCodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarcharLength() {
|
||||
return 10_485_760;
|
||||
|
@ -171,17 +196,17 @@ public class PostgreSQLDialect extends Dialect {
|
|||
@Override
|
||||
public int getMaxVarbinaryLength() {
|
||||
//postgres has no varbinary-like type
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName(int code, Size size) throws HibernateException {
|
||||
// The maximum scale for `interval second` is 6 unfortunately so we have to use numeric by default
|
||||
switch ( code ) {
|
||||
case SqlTypes.INTERVAL_SECOND:
|
||||
case INTERVAL_SECOND:
|
||||
final Integer scale = size.getScale();
|
||||
if ( scale == null || scale > 6 ) {
|
||||
return getTypeName( SqlTypes.NUMERIC, size );
|
||||
return getTypeName( NUMERIC, size );
|
||||
}
|
||||
}
|
||||
return super.getTypeName( code, size );
|
||||
|
@ -194,32 +219,27 @@ public class PostgreSQLDialect extends Dialect {
|
|||
int precision,
|
||||
int scale,
|
||||
JdbcTypeRegistry jdbcTypeRegistry) {
|
||||
if ( jdbcTypeCode == SqlTypes.OTHER ) {
|
||||
if ( jdbcTypeCode == OTHER ) {
|
||||
switch ( columnTypeName ) {
|
||||
case "uuid":
|
||||
jdbcTypeCode = SqlTypes.UUID;
|
||||
jdbcTypeCode = UUID;
|
||||
break;
|
||||
case "json":
|
||||
case "jsonb":
|
||||
jdbcTypeCode = SqlTypes.JSON;
|
||||
jdbcTypeCode = JSON;
|
||||
break;
|
||||
case "inet":
|
||||
jdbcTypeCode = SqlTypes.INET;
|
||||
jdbcTypeCode = INET;
|
||||
break;
|
||||
case "geometry":
|
||||
case "geography":
|
||||
jdbcTypeCode = SqlTypes.GEOMETRY;
|
||||
jdbcTypeCode = GEOMETRY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return jdbcTypeRegistry.getDescriptor( jdbcTypeCode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String currentTime() {
|
||||
return "localtime";
|
||||
|
|
|
@ -50,7 +50,6 @@ import org.hibernate.tool.schema.internal.StandardSequenceExporter;
|
|||
import org.hibernate.tool.schema.spi.Exporter;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.BasicTypeRegistry;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.SmallIntJdbcType;
|
||||
|
@ -60,13 +59,16 @@ import java.sql.SQLException;
|
|||
import java.sql.Types;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static org.hibernate.query.TemporalUnit.NANOSECOND;
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros;
|
||||
|
@ -79,12 +81,10 @@ import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithM
|
|||
public class SQLServerDialect extends AbstractTransactSQLDialect {
|
||||
private static final int PARAM_LIST_SIZE_LIMIT = 2100;
|
||||
|
||||
private final DatabaseVersion version;
|
||||
|
||||
private StandardSequenceExporter exporter;
|
||||
|
||||
public SQLServerDialect(DialectResolutionInfo info) {
|
||||
this( info.makeCopy() );
|
||||
this( info.makeCopy(), info );
|
||||
registerKeywords( info );
|
||||
}
|
||||
|
||||
|
@ -93,53 +93,71 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
|||
}
|
||||
|
||||
public SQLServerDialect(DatabaseVersion version) {
|
||||
super();
|
||||
this.version = version;
|
||||
this(version, null);
|
||||
}
|
||||
|
||||
//there is no 'double' type in SQL server
|
||||
//but 'float' is double precision by default
|
||||
registerColumnType( Types.DOUBLE, "float" );
|
||||
|
||||
if ( getVersion().isSameOrAfter( 10 ) ) {
|
||||
registerColumnType( Types.DATE, "date" );
|
||||
registerColumnType( Types.TIME, "time" );
|
||||
registerColumnType( Types.TIMESTAMP, "datetime2($p)" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "datetimeoffset($p)" );
|
||||
registerColumnType( SqlTypes.GEOMETRY, "geometry" );
|
||||
}
|
||||
protected SQLServerDialect(DatabaseVersion version, DialectResolutionInfo info) {
|
||||
super(version, info);
|
||||
|
||||
if ( getVersion().isSameOrAfter( 11 ) ) {
|
||||
exporter = new SqlServerSequenceExporter( this );
|
||||
}
|
||||
|
||||
if ( getVersion().isBefore( 9 ) ) {
|
||||
registerColumnType( Types.VARBINARY, "image" );
|
||||
registerColumnType( Types.VARCHAR, "text" );
|
||||
registerColumnType( Types.NVARCHAR, "text" );
|
||||
}
|
||||
else {
|
||||
registerKeyword( "top" );
|
||||
registerKeyword( "key" );
|
||||
}
|
||||
|
||||
// Use 'varchar(max)' and 'varbinary(max)' instead
|
||||
@Override
|
||||
protected List<Integer> getSupportedJdbcTypeCodes() {
|
||||
List<Integer> list = new ArrayList<>( super.getSupportedJdbcTypeCodes() );
|
||||
if ( getVersion().isSameOrAfter( 10 ) ) {
|
||||
list.add(GEOMETRY);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
if ( getVersion().isSameOrAfter( 10 ) ) {
|
||||
switch (jdbcTypeCode) {
|
||||
case DATE:
|
||||
return "date";
|
||||
case TIME:
|
||||
return "time";
|
||||
case TIMESTAMP:
|
||||
return"datetime2($p)";
|
||||
case TIMESTAMP_WITH_TIMEZONE:
|
||||
return "datetimeoffset($p)";
|
||||
}
|
||||
}
|
||||
|
||||
if ( getVersion().isSameOrAfter(9) ) {
|
||||
// Prefer 'varchar(max)' and 'varbinary(max)' to
|
||||
// the deprecated TEXT and IMAGE types. Note that
|
||||
// the length of a VARCHAR or VARBINARY column must
|
||||
// be either between 1 and 8000 or exactly MAX, and
|
||||
// the length of an NVARCHAR column must be either
|
||||
// between 1 and 4000 or exactly MAX.
|
||||
|
||||
// See http://www.sql-server-helper.com/faq/sql-server-2005-varchar-max-p01.aspx
|
||||
// See HHH-3965
|
||||
|
||||
registerColumnType( Types.BLOB, "varbinary(max)" );
|
||||
registerColumnType( Types.VARBINARY, "varbinary(max)" );
|
||||
|
||||
registerColumnType( Types.CLOB, "varchar(max)" );
|
||||
registerColumnType( Types.NCLOB, "nvarchar(max)" ); // HHH-8435 fix
|
||||
registerColumnType( Types.VARCHAR, "varchar(max)" );
|
||||
registerColumnType( Types.NVARCHAR, "nvarchar(max)" );
|
||||
// between 1 and 4000 or exactly MAX. (HHH-3965)
|
||||
switch (jdbcTypeCode) {
|
||||
case BLOB:
|
||||
return "varbinary(max)";
|
||||
case CLOB:
|
||||
return "varchar(max)";
|
||||
case NCLOB:
|
||||
return "nvarchar(max)";
|
||||
}
|
||||
}
|
||||
|
||||
registerKeyword( "top" );
|
||||
registerKeyword( "key" );
|
||||
switch (jdbcTypeCode) {
|
||||
case DOUBLE:
|
||||
// there is no 'double' type in SQL server
|
||||
// but 'float' is double precision by default
|
||||
return "float";
|
||||
case GEOMETRY:
|
||||
return "geometry";
|
||||
default:
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -152,11 +170,6 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
|||
return 4000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeZoneSupport getTimeZoneSupport() {
|
||||
return getVersion().isSameOrAfter( 10 ) ? TimeZoneSupport.NATIVE : TimeZoneSupport.NONE;
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.hibernate.type.StandardBasicTypes;
|
|||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static org.hibernate.dialect.SimpleDatabaseVersion.ZERO_VERSION;
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
|
||||
/**
|
||||
* Hibernate Dialect implementation for Cloud Spanner.
|
||||
|
@ -73,50 +74,61 @@ public class SpannerDialect extends Dialect {
|
|||
private static final UniqueDelegate NOOP_UNIQUE_DELEGATE = new DoNothingUniqueDelegate();
|
||||
|
||||
public SpannerDialect() {
|
||||
registerColumnType( Types.BOOLEAN, "bool" );
|
||||
|
||||
registerColumnType( Types.TINYINT, "int64" );
|
||||
registerColumnType( Types.SMALLINT, "int64" );
|
||||
registerColumnType( Types.INTEGER, "int64" );
|
||||
registerColumnType( Types.BIGINT, "int64" );
|
||||
|
||||
registerColumnType( Types.REAL, "float64" );
|
||||
registerColumnType( Types.FLOAT, "float64" );
|
||||
registerColumnType( Types.DOUBLE, "float64" );
|
||||
registerColumnType( Types.DECIMAL, "float64" );
|
||||
registerColumnType( Types.NUMERIC, "float64" );
|
||||
|
||||
//timestamp does not accept precision
|
||||
registerColumnType( Types.TIMESTAMP, "timestamp" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp" );
|
||||
//there is no time type of any kind
|
||||
registerColumnType( Types.TIME, "timestamp" );
|
||||
|
||||
registerColumnType( Types.CHAR, getMaxVarcharLength(), "string($l)" );
|
||||
registerColumnType( Types.CHAR, "string(max)" );
|
||||
registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "string($l)" );
|
||||
registerColumnType( Types.VARCHAR, "string(max)" );
|
||||
|
||||
registerColumnType( Types.NCHAR, getMaxNVarcharLength(), "string($l)" );
|
||||
registerColumnType( Types.NCHAR, "string(max)" );
|
||||
registerColumnType( Types.NVARCHAR, getMaxNVarcharLength(), "string($l)" );
|
||||
registerColumnType( Types.NVARCHAR, "string(max)" );
|
||||
|
||||
registerColumnType( Types.BINARY, getMaxBytesLength(), "bytes($l)" );
|
||||
registerColumnType( Types.BINARY, "bytes(max)" );
|
||||
registerColumnType( Types.VARBINARY, getMaxBytesLength(), "bytes($l)" );
|
||||
registerColumnType( Types.VARBINARY, "bytes(max)" );
|
||||
|
||||
registerColumnType( Types.CLOB, "string(max)" );
|
||||
registerColumnType( Types.NCLOB, "string(max)" );
|
||||
registerColumnType( Types.BLOB, "bytes(max)" );
|
||||
super();
|
||||
}
|
||||
|
||||
public SpannerDialect(DialectResolutionInfo info) {
|
||||
this();
|
||||
super();
|
||||
registerKeywords( info );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
switch (jdbcTypeCode) {
|
||||
case BOOLEAN:
|
||||
return "bool";
|
||||
|
||||
case TINYINT:
|
||||
case SMALLINT:
|
||||
case INTEGER:
|
||||
case BIGINT:
|
||||
return "int64";
|
||||
|
||||
case REAL:
|
||||
case FLOAT:
|
||||
case DOUBLE:
|
||||
case DECIMAL:
|
||||
case NUMERIC:
|
||||
return "float64";
|
||||
|
||||
//there is no time type of any kind
|
||||
case TIME:
|
||||
//timestamp does not accept precision
|
||||
case TIMESTAMP:
|
||||
case TIMESTAMP_WITH_TIMEZONE:
|
||||
return "timestamp";
|
||||
|
||||
case CHAR:
|
||||
case NCHAR:
|
||||
case VARCHAR:
|
||||
case NVARCHAR:
|
||||
return "string($l)";
|
||||
|
||||
case BINARY:
|
||||
case VARBINARY:
|
||||
return "bytes($l)";
|
||||
|
||||
case CLOB:
|
||||
case NCLOB:
|
||||
return "string(max)";
|
||||
case BLOB:
|
||||
return "bytes(max)";
|
||||
|
||||
default:
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarcharLength() {
|
||||
//max is equivalent to 2_621_440
|
||||
|
|
|
@ -16,6 +16,6 @@ package org.hibernate.dialect;
|
|||
@Deprecated
|
||||
public class Sybase11Dialect extends SybaseASEDialect {
|
||||
public Sybase11Dialect() {
|
||||
super( DatabaseVersion.make( 11 ), false, false );
|
||||
super( DatabaseVersion.make( 11 ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ package org.hibernate.dialect;
|
|||
public class SybaseASE157Dialect extends SybaseASEDialect {
|
||||
|
||||
public SybaseASE157Dialect() {
|
||||
super( DatabaseVersion.make( 15, 7 ), false, false );
|
||||
super( DatabaseVersion.make( 15, 7 ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ package org.hibernate.dialect;
|
|||
public class SybaseASE15Dialect extends SybaseASEDialect {
|
||||
|
||||
public SybaseASE15Dialect() {
|
||||
super( DatabaseVersion.make( 15 ), false, false );
|
||||
super( DatabaseVersion.make( 15 ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
|||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
||||
import static org.hibernate.type.SqlTypes.*;
|
||||
|
||||
/**
|
||||
* Dialect for Sybase Adaptive Server Enterprise for
|
||||
|
@ -54,55 +55,25 @@ public class SybaseASEDialect extends SybaseDialect {
|
|||
private final boolean ansiNull;
|
||||
|
||||
public SybaseASEDialect() {
|
||||
this( DatabaseVersion.make( 11 ), false, false );
|
||||
this( DatabaseVersion.make( 11 ) );
|
||||
}
|
||||
|
||||
public SybaseASEDialect(DialectResolutionInfo info) {
|
||||
this(
|
||||
info.makeCopy(),
|
||||
info.getDriverName() != null && info.getDriverName().contains( "jTDS" ),
|
||||
isAnsiNull( info.unwrap( DatabaseMetaData.class ) )
|
||||
);
|
||||
this( info.makeCopy(), info );
|
||||
registerKeywords( info );
|
||||
}
|
||||
|
||||
public SybaseASEDialect(DatabaseVersion version, boolean jtdsDriver, boolean ansiNull) {
|
||||
super( version, jtdsDriver );
|
||||
this.ansiNull = ansiNull;
|
||||
//On Sybase ASE, the 'bit' type cannot be null,
|
||||
//and cannot have indexes (while we don't use
|
||||
//tinyint to store signed bytes, we can use it
|
||||
//to store boolean values)
|
||||
registerColumnType( Types.BOOLEAN, "tinyint" );
|
||||
public SybaseASEDialect(DatabaseVersion version) {
|
||||
this(version, null);
|
||||
}
|
||||
|
||||
protected SybaseASEDialect(DatabaseVersion version, DialectResolutionInfo info) {
|
||||
super(version, info);
|
||||
|
||||
if ( getVersion().isSameOrAfter( 12 ) ) {
|
||||
//date / date were introduced in version 12
|
||||
registerColumnType( Types.DATE, "date" );
|
||||
registerColumnType( Types.TIME, "time" );
|
||||
if ( getVersion().isSameOrAfter( 15 ) ) {
|
||||
//bigint was added in version 15
|
||||
registerColumnType( Types.BIGINT, "bigint" );
|
||||
|
||||
if ( getVersion().isSameOrAfter( 15, 5 ) && !jtdsDriver ) {
|
||||
//According to Wikipedia bigdatetime and bigtime were added in 15.5
|
||||
//But with jTDS we can't use them as the driver can't handle the types
|
||||
registerColumnType( Types.DATE, "bigdatetime" );
|
||||
registerColumnType( Types.DATE, 3, "datetime" );
|
||||
registerColumnType( Types.TIME, "bigtime" );
|
||||
registerColumnType( Types.TIME, 3, "datetime" );
|
||||
registerColumnType( Types.TIMESTAMP, "bigdatetime" );
|
||||
registerColumnType( Types.TIMESTAMP, 3, "datetime" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "bigdatetime" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, 3, "datetime" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerColumnType( Types.VARBINARY, "image" );
|
||||
registerColumnType( Types.VARCHAR, "text" );
|
||||
ansiNull = info != null && isAnsiNull( info.unwrap( DatabaseMetaData.class ) );
|
||||
|
||||
registerSybaseKeywords();
|
||||
|
||||
sizeStrategy = new SizeStrategyImpl() {
|
||||
@Override
|
||||
public Size resolveSize(
|
||||
|
@ -123,6 +94,56 @@ public class SybaseASEDialect extends SybaseDialect {
|
|||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnType(int jdbcTypeCode) {
|
||||
|
||||
if ( jdbcTypeCode == BIGINT && getVersion().isBefore( 15 ) ) {
|
||||
// Sybase ASE didn't introduce 'bigint' until version 15.0
|
||||
return "numeric(19,0)";
|
||||
}
|
||||
|
||||
if ( getVersion().isSameOrAfter( 12 ) ) {
|
||||
// 'date' and 'time' were introduced in version 12
|
||||
// note: 'timestamp' is something weird on ASE,
|
||||
// not what we're looking for here!
|
||||
switch (jdbcTypeCode) {
|
||||
case DATE:
|
||||
return "date";
|
||||
case TIME:
|
||||
return "time";
|
||||
}
|
||||
}
|
||||
|
||||
switch (jdbcTypeCode) {
|
||||
case BOOLEAN:
|
||||
// On Sybase ASE, the 'bit' type cannot be null,
|
||||
// and cannot have indexes (while we don't use
|
||||
// tinyint to store signed bytes, we can use it
|
||||
// to store boolean values)
|
||||
return "tinyint";
|
||||
default:
|
||||
return super.columnType(jdbcTypeCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerDefaultColumnTypes(DialectResolutionInfo info) {
|
||||
super.registerDefaultColumnTypes(info);
|
||||
|
||||
// According to Wikipedia bigdatetime and bigtime were added in 15.5
|
||||
// But with jTDS we can't use them as the driver can't handle the types
|
||||
if ( getVersion().isSameOrAfter( 15, 5 ) && !jtdsDriver ) {
|
||||
registerColumnType( DATE, "bigdatetime" );
|
||||
registerColumnType( DATE, 3, "datetime" );
|
||||
registerColumnType( TIME, "bigtime" );
|
||||
registerColumnType( TIME, 3, "datetime" );
|
||||
registerColumnType( TIMESTAMP, "bigdatetime" );
|
||||
registerColumnType( TIMESTAMP, 3, "datetime" );
|
||||
registerColumnType( TIMESTAMP_WITH_TIMEZONE, "bigdatetime" );
|
||||
registerColumnType( TIMESTAMP_WITH_TIMEZONE, 3, "datetime" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarcharLength() {
|
||||
// the maximum length of a VARCHAR or VARBINARY
|
||||
|
|
|
@ -59,30 +59,39 @@ import jakarta.persistence.TemporalType;
|
|||
*/
|
||||
public class SybaseDialect extends AbstractTransactSQLDialect {
|
||||
|
||||
private final DatabaseVersion version;
|
||||
protected final boolean jtdsDriver;
|
||||
protected boolean jtdsDriver;
|
||||
|
||||
//All Sybase dialects share an IN list size limit.
|
||||
private static final int PARAM_LIST_SIZE_LIMIT = 250000;
|
||||
|
||||
public SybaseDialect(){
|
||||
this( DatabaseVersion.make( 11, 0 ), false );
|
||||
public SybaseDialect() {
|
||||
this( DatabaseVersion.make( 11, 0 ) );
|
||||
}
|
||||
|
||||
public SybaseDialect(DialectResolutionInfo info){
|
||||
this(
|
||||
info.makeCopy(),
|
||||
info.getDriverName() != null && info.getDriverName().contains( "jTDS" )
|
||||
);
|
||||
public SybaseDialect(DatabaseVersion version) {
|
||||
this(version, null);
|
||||
}
|
||||
|
||||
public SybaseDialect(DialectResolutionInfo info) {
|
||||
this( info.makeCopy(), info );
|
||||
registerKeywords( info );
|
||||
}
|
||||
|
||||
public SybaseDialect(DatabaseVersion version, boolean jtdsDriver) {
|
||||
super();
|
||||
this.version = version;
|
||||
this.jtdsDriver = jtdsDriver;
|
||||
//Sybase ASE didn't introduce bigint until version 15.0
|
||||
registerColumnType( Types.BIGINT, "numeric(19,0)" );
|
||||
protected SybaseDialect(DatabaseVersion version, DialectResolutionInfo info) {
|
||||
super(version, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerDefaultColumnTypes(DialectResolutionInfo info) {
|
||||
// we need to check init the jtdsDriver field here,
|
||||
// because we need it in the registerDefaultColumnTypes()
|
||||
// of the subclass, which is called from the superclass
|
||||
// constructor, before our constructor has been called
|
||||
jtdsDriver = info != null
|
||||
&& info.getDriverName() != null
|
||||
&& info.getDriverName().contains( "jTDS" );
|
||||
|
||||
super.registerDefaultColumnTypes(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -146,11 +155,6 @@ public class SybaseDialect extends AbstractTransactSQLDialect {
|
|||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsNullPrecedence() {
|
||||
return false;
|
||||
|
@ -314,7 +318,7 @@ public class SybaseDialect extends AbstractTransactSQLDialect {
|
|||
|
||||
@Override
|
||||
public NameQualifierSupport getNameQualifierSupport() {
|
||||
if ( version.isSameOrAfter( 15 ) ) {
|
||||
if ( getVersion().isSameOrAfter( 15 ) ) {
|
||||
return NameQualifierSupport.BOTH;
|
||||
}
|
||||
return NameQualifierSupport.CATALOG;
|
||||
|
|
|
@ -29,29 +29,30 @@ import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
|||
*/
|
||||
public class TiDBDialect extends MySQLDialect {
|
||||
|
||||
private final int tidbVersion;
|
||||
private final DatabaseVersion tidbVersion;
|
||||
|
||||
public TiDBDialect() {
|
||||
// Let's be conservative and assume people use a 4 byte character set
|
||||
this( 500, 4 );
|
||||
this( DatabaseVersion.make(5, 4) );
|
||||
}
|
||||
|
||||
public TiDBDialect(DialectResolutionInfo info) {
|
||||
this(
|
||||
info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10,
|
||||
getCharacterSetBytesPerCharacter( info.unwrap( DatabaseMetaData.class ) )
|
||||
);
|
||||
this( info.makeCopy(), info );
|
||||
registerKeywords( info );
|
||||
}
|
||||
|
||||
public TiDBDialect(int version, int characterSetBytesPerCharacter) {
|
||||
public TiDBDialect(DatabaseVersion version) {
|
||||
this(version, null);
|
||||
}
|
||||
|
||||
protected TiDBDialect(DatabaseVersion tidbVersion, DialectResolutionInfo info) {
|
||||
// For simplicity’s sake, configure MySQL 5.7 compatibility
|
||||
super( DatabaseVersion.make( 5, 7 ), characterSetBytesPerCharacter );
|
||||
this.tidbVersion = version;
|
||||
super( DatabaseVersion.make( 5, 7 ), info );
|
||||
this.tidbVersion = tidbVersion;
|
||||
registerKeywords();
|
||||
}
|
||||
|
||||
public int getTidbVersion() {
|
||||
@Override
|
||||
public DatabaseVersion getVersion() {
|
||||
return tidbVersion;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue