Search in sources :

Example 1 with CoalesceIfnullEmulation

use of org.hibernate.dialect.function.CoalesceIfnullEmulation in project hibernate-orm by hibernate.

the class Dialect method initializeFunctionRegistry.

/**
 * Initialize the given registry with any dialect-specific functions.
 * <p>
 * Support for certain SQL functions is required, and if the database
 * does not support a required function, then the dialect must define
 * a way to emulate it.
 * <p>
 * These required functions include the functions defined by the JPA
 * query language specification:
 *
 * <ul>
 * <li> avg(arg)							- aggregate function
 * <li> count([distinct ]arg)				- aggregate function
 * <li> max(arg)							- aggregate function
 * <li> min(arg)							- aggregate function
 * <li> sum(arg)							- aggregate function
 * </ul>
 *
 * <ul>
 * <li> coalesce(arg0, arg1, ...)
 * <li> nullif(arg0, arg1)
 * </ul>
 *
 * <ul>
 * <li> lower(arg)
 * <li> upper(arg)
 * <li> length(arg)
 * <li> concat(arg0, arg1, ...)
 * <li> locate(pattern, string[, start])
 * <li> substring(string, start[, length])
 * <li> trim([[spec ][character ]from] string)
 * </ul>
 *
 * <ul>
 * <li> abs(arg)
 * <li> mod(arg0, arg1)
 * <li> sqrt(arg)
 * </ul>
 *
 * <ul>
 * <li> current date
 * <li> current time
 * <li> current timestamp
 * </ul>
 *
 * Along with an additional set of functions defined by ANSI SQL:
 *
 * <ul>
 * <li> any(arg)							- aggregate function
 * <li> every(arg)							- aggregate function
 * </ul>
 *
 * <ul>
 * <li> cast(arg as Type)
 * <li> extract(field from arg)
 * </ul>
 *
 * <ul>
 * <li> ln(arg)
 * <li> exp(arg)
 * <li> power(arg0, arg1)
 * <li> floor(arg)
 * <li> ceiling(arg)
 * </ul>
 *
 * <ul>
 * <li> position(pattern in string)
 * <li> substring(string from start[ for length])
 * <li> overlay(string placing replacement from start[ for length])
 * </ul>
 *
 * And the following functions for working with java.time types:
 *
 * <ul>
 * <li> local date
 * <li> local time
 * <li> local datetime
 * <li> offset datetime
 * <li> instant
 * </ul>
 *
 * And a number of additional "standard" functions:
 *
 * <ul>
 * <li> left(string, length)
 * <li> right(string, length)
 * <li> replace(string, pattern, replacement)
 * <li> pad(string with length spec[ character])
 * </ul>
 *
 * <ul>
 * <li> log10(arg)
 * <li> sign(arg)
 * <li> sin(arg)
 * <li> cos(arg)
 * <li> tan(arg)
 * <li> asin(arg)
 * <li> acos(arg)
 * <li> atan(arg)
 * <li> atan2(arg0, arg1)
 * <li> round(arg0, arg1)
 * <li> least(arg0, arg1, ...)
 * <li> greatest(arg0, arg1, ...)
 * </ul>
 *
 * <ul>
 * <li> format(datetime as pattern)
 * <li> collate(string as collation)
 * <li> str(arg)					- synonym of cast(a as String)
 * <li> ifnull(arg0, arg1)			- synonym of coalesce(a, b)
 * </ul>
 *
 * Finally, the following functions are defined as abbreviations
 * for extract(), and desugared by the parser:
 *
 * <ul>
 * <li> second(arg)					- synonym of extract(second from a)
 * <li> minute(arg)					- synonym of extract(minute from a)
 * <li> hour(arg)					- synonym of extract(hour from a)
 * <li> day(arg)					- synonym of extract(day from a)
 * <li> month(arg)					- synonym of extract(month from a)
 * <li> year(arg)					- synonym of extract(year from a)
 * </ul>
 *
 * Note that according to this definition, the second() function returns
 * a floating point value, contrary to the integer type returned by the
 * native function with this name on many databases. Thus, we don't just
 * naively map these HQL functions to the native SQL functions with the
 * same names.
 */
public void initializeFunctionRegistry(QueryEngine queryEngine) {
    final TypeConfiguration typeConfiguration = queryEngine.getTypeConfiguration();
    final BasicTypeRegistry basicTypeRegistry = typeConfiguration.getBasicTypeRegistry();
    final BasicType<Date> timestampType = basicTypeRegistry.resolve(StandardBasicTypes.TIMESTAMP);
    final BasicType<Date> dateType = basicTypeRegistry.resolve(StandardBasicTypes.DATE);
    final BasicType<Date> timeType = basicTypeRegistry.resolve(StandardBasicTypes.TIME);
    final BasicType<Instant> instantType = basicTypeRegistry.resolve(StandardBasicTypes.INSTANT);
    final BasicType<OffsetDateTime> offsetDateTimeType = basicTypeRegistry.resolve(StandardBasicTypes.OFFSET_DATE_TIME);
    final BasicType<LocalDateTime> localDateTimeType = basicTypeRegistry.resolve(StandardBasicTypes.LOCAL_DATE_TIME);
    final BasicType<LocalTime> localTimeType = basicTypeRegistry.resolve(StandardBasicTypes.LOCAL_TIME);
    final BasicType<LocalDate> localDateType = basicTypeRegistry.resolve(StandardBasicTypes.LOCAL_DATE);
    CommonFunctionFactory functionFactory = new CommonFunctionFactory(queryEngine);
    // aggregate functions, supported on every database
    functionFactory.aggregates(this, SqlAstNodeRenderingMode.DEFAULT);
    // the ANSI SQL-defined aggregate functions any() and every() are only
    // supported on one database, but can be emulated using sum() and case,
    // though there is a more natural mapping on some databases
    functionFactory.everyAny_sumCase();
    // math functions supported on almost every database
    // Note that while certain mathematical functions return the same type
    // as their arguments, this is not the case in general - any function
    // involving exponentiation by a non-integer power, logarithms,
    // trigonometric functions, etc., should be considered to be of type
    // Double. In particular, there is no meaningful concept of an "exact
    // decimal" version of these functions, and if any database attempted
    // to implement such a silly thing, it would be dog slow.
    functionFactory.math();
    // trig functions supported on almost every database
    functionFactory.trigonometry();
    // coalesce() function, supported by most databases, must be emulated
    // in terms of nvl() for platforms which don't support it natively
    functionFactory.coalesce();
    // nullif() function, supported on almost every database
    functionFactory.nullif();
    // string functions, must be emulated where not supported
    functionFactory.leftRight();
    functionFactory.replace();
    functionFactory.concat();
    functionFactory.lowerUpper();
    // there are two forms of substring(), the JPA standard syntax, which
    // separates arguments using commas, and the ANSI SQL standard syntax
    // with named arguments (we support both)
    functionFactory.substring();
    // the JPA locate() function is especially tricky to emulate, calling
    // for lots of Dialect-specific customization
    functionFactory.locate();
    // JPA string length() function, a synonym for ANSI SQL character_length()
    functionFactory.length_characterLength();
    // only some databases support the ANSI SQL-style position() function, so
    // define it here as an alias for locate()
    queryEngine.getSqmFunctionRegistry().register("position", new LocatePositionEmulation(typeConfiguration));
    // very few databases support ANSI-style overlay() function, so emulate
    // it here in terms of either insert() or concat()/substring()
    queryEngine.getSqmFunctionRegistry().register("overlay", new InsertSubstringOverlayEmulation(typeConfiguration, false));
    // ANSI SQL trim() function is supported on almost all of the databases
    // we care about, but on some it must be emulated using ltrim(), rtrim(),
    // and replace()
    queryEngine.getSqmFunctionRegistry().register("trim", new TrimFunction(this, typeConfiguration));
    // ANSI SQL cast() function is supported on the databases we care most
    // about but in certain cases it doesn't allow some useful typecasts,
    // which must be emulated in a dialect-specific way
    // Note that two case are especially tricky to make portable:
    // - casts to and from Boolean, and
    // - casting Double or Float to String.
    queryEngine.getSqmFunctionRegistry().register("cast", new CastFunction(this, queryEngine.getPreferredSqlTypeCodeForBoolean()));
    // There is a 'collate' operator in a number of major databases
    functionFactory.collate();
    // ANSI SQL extract() function is supported on the databases we care most
    // about (though it is called datepart() in some of them) but HQL defines
    // additional non-standard temporal field types, which must be emulated in
    // a very dialect-specific way
    queryEngine.getSqmFunctionRegistry().register("extract", new ExtractFunction(this, typeConfiguration));
    // comparison functions supported on most databases, emulated on others
    // using a case expression
    functionFactory.leastGreatest();
    // two-argument synonym for coalesce() supported on most but not every
    // database, so define it here as an alias for coalesce(arg1,arg2)
    queryEngine.getSqmFunctionRegistry().register("ifnull", new CoalesceIfnullEmulation());
    // rpad() and pad() are supported on almost every database, and emulated
    // where not supported, but they're not considered "standard" ... instead
    // they're used to implement pad()
    functionFactory.pad();
    // pad() is a function we've designed to look like ANSI trim()
    queryEngine.getSqmFunctionRegistry().register("pad", new LpadRpadPadEmulation(typeConfiguration));
    // legacy Hibernate convenience function for casting to string, defined
    // here as an alias for cast(arg as String)
    queryEngine.getSqmFunctionRegistry().register("str", new CastStrEmulation(typeConfiguration));
    // format() function for datetimes, emulated on many databases using the
    // Oracle-style to_char() function, and on others using their native
    // formatting functions
    functionFactory.format_toChar();
    // timestampadd()/timestampdiff() delegated back to the Dialect itself
    // since there is a great variety of different ways to emulate them
    queryEngine.getSqmFunctionRegistry().register("timestampadd", new TimestampaddFunction(this, typeConfiguration));
    queryEngine.getSqmFunctionRegistry().register("timestampdiff", new TimestampdiffFunction(this, typeConfiguration));
    queryEngine.getSqmFunctionRegistry().registerAlternateKey("dateadd", "timestampadd");
    queryEngine.getSqmFunctionRegistry().registerAlternateKey("datediff", "timestampdiff");
    // ANSI SQL (and JPA) current date/time/timestamp functions, supported
    // natively on almost every database, delegated back to the Dialect
    queryEngine.getSqmFunctionRegistry().register("current_date", new CurrentFunction("current_date", currentDate(), dateType));
    queryEngine.getSqmFunctionRegistry().register("current_time", new CurrentFunction("current_time", currentTime(), timeType));
    queryEngine.getSqmFunctionRegistry().register("current_timestamp", new CurrentFunction("current_timestamp", currentTimestamp(), timestampType));
    queryEngine.getSqmFunctionRegistry().registerAlternateKey("current date", "current_date");
    queryEngine.getSqmFunctionRegistry().registerAlternateKey("current time", "current_time");
    queryEngine.getSqmFunctionRegistry().registerAlternateKey("current timestamp", "current_timestamp");
    // HQL current instant/date/time/datetime functions, delegated back to the Dialect
    queryEngine.getSqmFunctionRegistry().register("local_date", new CurrentFunction("local_date", currentDate(), localDateType));
    queryEngine.getSqmFunctionRegistry().register("local_time", new CurrentFunction("local_time", currentLocalTime(), localTimeType));
    queryEngine.getSqmFunctionRegistry().register("local_datetime", new CurrentFunction("local_datetime", currentLocalTimestamp(), localDateTimeType));
    queryEngine.getSqmFunctionRegistry().register("offset_datetime", new CurrentFunction("offset_datetime", currentTimestampWithTimeZone(), offsetDateTimeType));
    queryEngine.getSqmFunctionRegistry().registerAlternateKey("local date", "local_date");
    queryEngine.getSqmFunctionRegistry().registerAlternateKey("local time", "local_time");
    queryEngine.getSqmFunctionRegistry().registerAlternateKey("local datetime", "local_datetime");
    queryEngine.getSqmFunctionRegistry().registerAlternateKey("offset datetime", "offset_datetime");
    queryEngine.getSqmFunctionRegistry().register("instant", new CurrentFunction("instant", currentTimestamp(), instantType));
    // deprecated legacy!
    queryEngine.getSqmFunctionRegistry().registerAlternateKey("current_instant", "instant");
    queryEngine.getSqmFunctionRegistry().register("sql", new SqlFunction());
}
Also used : LocalDateTime(java.time.LocalDateTime) CastStrEmulation(org.hibernate.dialect.function.CastStrEmulation) LocalDate(java.time.LocalDate) LpadRpadPadEmulation(org.hibernate.dialect.function.LpadRpadPadEmulation) InsertSubstringOverlayEmulation(org.hibernate.dialect.function.InsertSubstringOverlayEmulation) ExtractFunction(org.hibernate.dialect.function.ExtractFunction) CommonFunctionFactory(org.hibernate.dialect.function.CommonFunctionFactory) CastFunction(org.hibernate.dialect.function.CastFunction) CurrentFunction(org.hibernate.dialect.function.CurrentFunction) LocalTime(java.time.LocalTime) Instant(java.time.Instant) TimestampdiffFunction(org.hibernate.dialect.function.TimestampdiffFunction) Date(java.util.Date) LocalDate(java.time.LocalDate) DateTimeUtils.appendAsDate(org.hibernate.type.descriptor.DateTimeUtils.appendAsDate) CoalesceIfnullEmulation(org.hibernate.dialect.function.CoalesceIfnullEmulation) TrimFunction(org.hibernate.dialect.function.TrimFunction) OffsetDateTime(java.time.OffsetDateTime) TimestampaddFunction(org.hibernate.dialect.function.TimestampaddFunction) BasicTypeRegistry(org.hibernate.type.BasicTypeRegistry) TypeConfiguration(org.hibernate.type.spi.TypeConfiguration) LocatePositionEmulation(org.hibernate.dialect.function.LocatePositionEmulation) SqlFunction(org.hibernate.dialect.function.SqlFunction)

Aggregations

Instant (java.time.Instant)1 LocalDate (java.time.LocalDate)1 LocalDateTime (java.time.LocalDateTime)1 LocalTime (java.time.LocalTime)1 OffsetDateTime (java.time.OffsetDateTime)1 Date (java.util.Date)1 CastFunction (org.hibernate.dialect.function.CastFunction)1 CastStrEmulation (org.hibernate.dialect.function.CastStrEmulation)1 CoalesceIfnullEmulation (org.hibernate.dialect.function.CoalesceIfnullEmulation)1 CommonFunctionFactory (org.hibernate.dialect.function.CommonFunctionFactory)1 CurrentFunction (org.hibernate.dialect.function.CurrentFunction)1 ExtractFunction (org.hibernate.dialect.function.ExtractFunction)1 InsertSubstringOverlayEmulation (org.hibernate.dialect.function.InsertSubstringOverlayEmulation)1 LocatePositionEmulation (org.hibernate.dialect.function.LocatePositionEmulation)1 LpadRpadPadEmulation (org.hibernate.dialect.function.LpadRpadPadEmulation)1 SqlFunction (org.hibernate.dialect.function.SqlFunction)1 TimestampaddFunction (org.hibernate.dialect.function.TimestampaddFunction)1 TimestampdiffFunction (org.hibernate.dialect.function.TimestampdiffFunction)1 TrimFunction (org.hibernate.dialect.function.TrimFunction)1 BasicTypeRegistry (org.hibernate.type.BasicTypeRegistry)1