org.hibernate.community.dialect.MaxDBDialect Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-community-dialects Show documentation
Show all versions of hibernate-community-dialects Show documentation
Hibernate's community supported dialects
The newest version!
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.community.dialect;
import java.sql.DatabaseMetaData;
import java.sql.Types;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.community.dialect.sequence.MaxDBSequenceSupport;
import org.hibernate.community.dialect.sequence.SequenceInformationExtractorSAPDBDatabaseImpl;
import org.hibernate.dialect.AbstractTransactSQLDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitLimitHandler;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.temptable.TemporaryTable;
import org.hibernate.dialect.temptable.TemporaryTableKind;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.sqm.TrimSpec;
import org.hibernate.query.sqm.mutation.spi.AfterUseAction;
import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableInsertStrategy;
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.BasicType;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
import static org.hibernate.dialect.SimpleDatabaseVersion.ZERO_VERSION;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING;
import static org.hibernate.type.SqlTypes.BIGINT;
import static org.hibernate.type.SqlTypes.BLOB;
import static org.hibernate.type.SqlTypes.CLOB;
import static org.hibernate.type.SqlTypes.DECIMAL;
import static org.hibernate.type.SqlTypes.NUMERIC;
import static org.hibernate.type.SqlTypes.TIMESTAMP;
import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE;
import static org.hibernate.type.SqlTypes.TINYINT;
import static org.hibernate.type.SqlTypes.VARBINARY;
/**
* A SQL dialect compatible with SAP MaxDB.
*
* @author Brad Clow
*/
public class MaxDBDialect extends Dialect {
public MaxDBDialect() {
super( ZERO_VERSION );
}
public MaxDBDialect(DialectResolutionInfo info) {
super( info );
}
@Override
protected String columnType(int sqlTypeCode) {
switch ( sqlTypeCode ) {
case TINYINT:
return "smallint";
case BIGINT:
return "fixed(19,0)";
case NUMERIC:
case DECIMAL:
return "fixed($p,$s)";
//no explicit precision
case TIMESTAMP:
case TIMESTAMP_WITH_TIMEZONE:
return "timestamp";
case VARBINARY:
case BLOB:
return "long byte";
case CLOB:
return "long varchar";
default:
return super.columnType( sqlTypeCode );
}
}
@Override
public int getMaxVarbinaryLength() {
// there's no varbinary type
return -1;
}
@Override
public JdbcType resolveSqlTypeDescriptor(
String columnTypeName,
int jdbcTypeCode,
int precision,
int scale,
JdbcTypeRegistry jdbcTypeRegistry) {
switch ( jdbcTypeCode ) {
case Types.NUMERIC:
case Types.DECIMAL:
if ( precision == 19 && scale == 0 ) {
return jdbcTypeRegistry.getDescriptor( Types.BIGINT );
}
}
return super.resolveSqlTypeDescriptor(
columnTypeName,
jdbcTypeCode,
precision,
scale,
jdbcTypeRegistry
);
}
@Override
public int getDefaultStatementBatchSize() {
return 15;
}
@Override
public LimitHandler getLimitHandler() {
return LimitLimitHandler.INSTANCE;
}
@Override
public void initializeFunctionRegistry(FunctionContributions functionContributions) {
super.initializeFunctionRegistry(functionContributions);
CommonFunctionFactory functionFactory = new CommonFunctionFactory(functionContributions);
functionFactory.log();
functionFactory.pi();
functionFactory.cot();
functionFactory.cosh();
functionFactory.sinh();
functionFactory.tanh();
functionFactory.radians();
functionFactory.degrees();
functionFactory.trunc();
functionFactory.trim2();
functionFactory.substr();
functionFactory.substring_substr();
functionFactory.translate();
functionFactory.initcap();
functionFactory.soundex();
functionFactory.yearMonthDay();
functionFactory.hourMinuteSecond();
functionFactory.dayofweekmonthyear();
functionFactory.daynameMonthname();
functionFactory.dateTimeTimestamp();
functionFactory.ceiling_ceil();
functionFactory.week_weekofyear();
functionFactory.concat_pipeOperator();
functionFactory.coalesce_value();
//since lpad/rpad are not actually useful padding
//functions, map them to lfill/rfill
functionFactory.pad_fill();
functionFactory.datediff();
functionFactory.adddateSubdateAddtimeSubtime();
functionFactory.addMonths();
final BasicType integerType = functionContributions.getTypeConfiguration().getBasicTypeRegistry()
.resolve( StandardBasicTypes.INTEGER );
functionContributions.getFunctionRegistry().registerPattern( "extract", "?1(?2)", integerType );
functionContributions.getFunctionRegistry().patternDescriptorBuilder( "nullif", "case ?1 when ?2 then null else ?1 end" )
.setExactArgumentCount(2)
.register();
functionContributions.getFunctionRegistry().namedDescriptorBuilder( "index" )
.setInvariantType( integerType )
.setArgumentCountBetween( 2, 4 )
.register();
functionContributions.getFunctionRegistry().registerBinaryTernaryPattern(
"locate",
integerType, "index(?2,?1)", "index(?2,?1,?3)",
STRING, STRING, INTEGER,
functionContributions.getTypeConfiguration()
).setArgumentListSignature("(pattern, string[, start])");
}
@Override
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
return new StandardSqlAstTranslatorFactory() {
@Override
protected SqlAstTranslator buildTranslator(
SessionFactoryImplementor sessionFactory, Statement statement) {
return new MaxDBSqlAstTranslator<>( sessionFactory, statement );
}
};
}
@Override
public String trimPattern(TrimSpec specification, boolean isWhitespace) {
return AbstractTransactSQLDialect.replaceLtrimRtrim( specification, isWhitespace );
}
@Override
public boolean dropConstraints() {
return false;
}
@Override
public String getAddColumnString() {
return "add";
}
@Override
public String getAddForeignKeyConstraintString(
String constraintName,
String[] foreignKey,
String referencedTable,
String[] primaryKey,
boolean referencesPrimaryKey) {
final StringBuilder res = new StringBuilder( 30 )
.append( " foreign key " )
.append( constraintName )
.append( " (" )
.append( String.join( ", ", foreignKey ) )
.append( ") references " )
.append( referencedTable );
if ( !referencesPrimaryKey ) {
res.append( " (" )
.append( String.join( ", ", primaryKey ) )
.append( ')' );
}
return res.toString();
}
public String getAddForeignKeyConstraintString(
String constraintName,
String foreignKeyDefinition) {
return foreignKeyDefinition;
}
@Override
public String getAddPrimaryKeyConstraintString(String constraintName) {
return " primary key ";
}
@Override
public String getNullColumnString() {
return " null";
}
@Override
public SequenceSupport getSequenceSupport() {
return MaxDBSequenceSupport.INSTANCE;
}
@Override
public String getQuerySequencesString() {
return "select * from domain.sequences";
}
@Override
public SequenceInformationExtractor getSequenceInformationExtractor() {
return SequenceInformationExtractorSAPDBDatabaseImpl.INSTANCE;
}
@Override
public boolean supportsOffsetInSubquery() {
return true;
}
@Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
return new LocalTemporaryTableMutationStrategy(
TemporaryTable.createIdTable(
rootEntityDescriptor,
basename -> "temp." + TemporaryTable.ID_TABLE_PREFIX + basename,
this,
runtimeModelCreationContext
),
runtimeModelCreationContext.getSessionFactory()
);
}
@Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) {
return new LocalTemporaryTableInsertStrategy(
TemporaryTable.createEntityTable(
rootEntityDescriptor,
name -> "temp." + TemporaryTable.ENTITY_TABLE_PREFIX + name,
this,
runtimeModelCreationContext
),
runtimeModelCreationContext.getSessionFactory()
);
}
@Override
public BeforeUseAction getTemporaryTableBeforeUseAction() {
return BeforeUseAction.CREATE;
}
@Override
public AfterUseAction getTemporaryTableAfterUseAction() {
return AfterUseAction.DROP;
}
@Override
public TemporaryTableKind getSupportedTemporaryTableKind() {
return TemporaryTableKind.LOCAL;
}
@Override
public String getTemporaryTableCreateOptions() {
return "ignore rollback";
}
@Override
public boolean supportsJdbcConnectionLobCreation(DatabaseMetaData databaseMetaData) {
return false;
}
@Override
public String getDual() {
return "dual";
}
@Override
public String getFromDualForSelectOnly() {
return " from " + getDual();
}
}