HHH-13785 : HQL/Criteria function support
- temporal literals - generalized literals - literal formatters (SQL string generation) - FORMAT function
This commit is contained in:
parent
6e0d15b134
commit
eab6107ec2
|
@ -0,0 +1,33 @@
|
||||||
|
= Query
|
||||||
|
|
||||||
|
== Expressions
|
||||||
|
|
||||||
|
=== Paths
|
||||||
|
|
||||||
|
=== Literals
|
||||||
|
|
||||||
|
=== Parameters
|
||||||
|
|
||||||
|
=== Unary expressions
|
||||||
|
|
||||||
|
=== Arithmetic operations
|
||||||
|
|
||||||
|
Numeric v. temporal
|
||||||
|
|
||||||
|
=== Functions
|
||||||
|
|
||||||
|
- Standard functions
|
||||||
|
- SqmFunctionRegistry
|
||||||
|
- Role of Dialect
|
||||||
|
|
||||||
|
=== Concatenation operations
|
||||||
|
|
||||||
|
=== Entity-type references
|
||||||
|
|
||||||
|
=== CASE statements
|
||||||
|
|
||||||
|
=== COALESCE statements
|
||||||
|
|
||||||
|
=== NULLIF statements
|
||||||
|
|
||||||
|
=== Sub-queries
|
|
@ -0,0 +1,10 @@
|
||||||
|
`OffsetDateTime` is not safe to store in database. This form does not understand "zone rules" relating to things
|
||||||
|
such as DST. An offset of +5, e.g., does not change when DST starts/ends - its just +5.
|
||||||
|
|
||||||
|
A `ZonedDateTime` on the other hand knows the actual timezone as well as the offset for the LocalDateTime portion in
|
||||||
|
that timezone. It is much more complete picture of the actual Instant.
|
||||||
|
|
||||||
|
The proper solution for storing "with tz" would be to always use a `ZonedDateTime`, converted from `OffsetDateTime`
|
||||||
|
if needed. In this case, I assume we need to transform a `LocalDateTime` to `ZonedDateTime`?
|
||||||
|
|
||||||
|
^^ what about Dialects that do not support "with tz" datatype variants? Are there any anymore?
|
|
@ -13,7 +13,7 @@ ext {
|
||||||
junitVintageVersion = '5.3.1'
|
junitVintageVersion = '5.3.1'
|
||||||
junit5Version = '5.3.1'
|
junit5Version = '5.3.1'
|
||||||
|
|
||||||
h2Version = '1.4.196'
|
h2Version = '1.4.199'
|
||||||
bytemanVersion = '4.0.8' //Compatible with JDK14
|
bytemanVersion = '4.0.8' //Compatible with JDK14
|
||||||
jnpVersion = '5.0.6.CR1'
|
jnpVersion = '5.0.6.CR1'
|
||||||
|
|
||||||
|
|
|
@ -11,60 +11,91 @@ lexer grammar HqlLexer;
|
||||||
package org.hibernate.grammars.hql;
|
package org.hibernate.grammars.hql;
|
||||||
}
|
}
|
||||||
|
|
||||||
WS : ( ' ' | '\t' | '\f' | EOL ) -> skip;
|
WS : WS_CHAR+ -> skip;
|
||||||
|
|
||||||
fragment
|
fragment
|
||||||
EOL : [\r\n]+;
|
WS_CHAR : [ \f\t\r\n];
|
||||||
|
|
||||||
INTEGER_LITERAL : INTEGER_NUMBER ;
|
|
||||||
|
|
||||||
fragment
|
fragment
|
||||||
INTEGER_NUMBER : ('0' | '1'..'9' '0'..'9'*) ;
|
DIGIT : [0-9];
|
||||||
|
|
||||||
LONG_LITERAL : INTEGER_NUMBER ('l'|'L');
|
|
||||||
|
|
||||||
BIG_INTEGER_LITERAL : INTEGER_NUMBER ('bi'|'BI') ;
|
|
||||||
|
|
||||||
HEX_LITERAL : '0' ('x'|'X') HEX_DIGIT+ ('l'|'L')? ;
|
|
||||||
|
|
||||||
fragment
|
fragment
|
||||||
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
|
HEX_DIGIT : [0-9a-fA-F];
|
||||||
|
|
||||||
OCTAL_LITERAL : '0' ('0'..'7')+ ('l'|'L')? ;
|
fragment
|
||||||
|
EXPONENT : [eE] [+-]? DIGIT+;
|
||||||
|
|
||||||
FLOAT_LITERAL : FLOATING_POINT_NUMBER ('f'|'F')? ;
|
fragment
|
||||||
|
LONG_SUFFIX : [lL];
|
||||||
|
|
||||||
|
fragment
|
||||||
|
FLOAT_SUFFIX : [fF];
|
||||||
|
|
||||||
|
fragment
|
||||||
|
DOUBLE_SUFFIX : [dD];
|
||||||
|
|
||||||
|
fragment
|
||||||
|
BIG_DECIMAL_SUFFIX : [bB] [dD];
|
||||||
|
|
||||||
|
fragment
|
||||||
|
BIG_INTEGER_SUFFIX : [bB] [iI];
|
||||||
|
|
||||||
|
fragment
|
||||||
|
INTEGER_NUMBER
|
||||||
|
: DIGIT+
|
||||||
|
;
|
||||||
|
|
||||||
fragment
|
fragment
|
||||||
FLOATING_POINT_NUMBER
|
FLOATING_POINT_NUMBER
|
||||||
: ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
|
: DIGIT+ '.' DIGIT* EXPONENT?
|
||||||
| '.' ('0'..'9')+ EXPONENT?
|
| '.' DIGIT+ EXPONENT?
|
||||||
| ('0'..'9')+ EXPONENT
|
| DIGIT+ EXPONENT
|
||||||
| ('0'..'9')+
|
| DIGIT+
|
||||||
;
|
;
|
||||||
|
|
||||||
DOUBLE_LITERAL : FLOATING_POINT_NUMBER ('d'|'D') ;
|
|
||||||
|
|
||||||
BIG_DECIMAL_LITERAL : FLOATING_POINT_NUMBER ('bd'|'BD') ;
|
|
||||||
|
|
||||||
fragment
|
fragment SINGLE_QUOTE : '\'';
|
||||||
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;
|
fragment DOUBLE_QUOTE : '"';
|
||||||
|
|
||||||
CHARACTER_LITERAL
|
fragment BACKSLASH : '\\';
|
||||||
: '\'' ( ESCAPE_SEQUENCE | ~('\''|'\\') ) '\'' {setText(getText().substring(1, getText().length()-1));}
|
|
||||||
;
|
|
||||||
|
|
||||||
STRING_LITERAL
|
|
||||||
: '"' ( ESCAPE_SEQUENCE | ~('\\'|'"') )* '"' {setText(getText().substring(1, getText().length()-1));}
|
|
||||||
| ('\'' ( ESCAPE_SEQUENCE | ~('\\'|'\'') )* '\'')+ {setText(getText().substring(1, getText().length()-1).replace("''", "'"));}
|
|
||||||
;
|
|
||||||
|
|
||||||
fragment
|
fragment
|
||||||
ESCAPE_SEQUENCE
|
ESCAPE_SEQUENCE
|
||||||
: '\\' ('b'|'t'|'n'|'f'|'r'|'\\"'|'\''|'\\')
|
: BACKSLASH [btnfr"']
|
||||||
| UNICODE_ESCAPE
|
| BACKSLASH UNICODE_ESCAPE
|
||||||
| OCTAL_ESCAPE
|
| BACKSLASH BACKSLASH
|
||||||
;
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
UNICODE_ESCAPE
|
||||||
|
: 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
|
||||||
|
;
|
||||||
|
|
||||||
|
INTEGER_LITERAL : INTEGER_NUMBER ;
|
||||||
|
|
||||||
|
LONG_LITERAL : INTEGER_NUMBER LONG_SUFFIX;
|
||||||
|
|
||||||
|
FLOAT_LITERAL : FLOATING_POINT_NUMBER FLOAT_SUFFIX?;
|
||||||
|
|
||||||
|
DOUBLE_LITERAL : FLOATING_POINT_NUMBER DOUBLE_SUFFIX;
|
||||||
|
|
||||||
|
BIG_INTEGER_LITERAL : INTEGER_NUMBER BIG_INTEGER_SUFFIX;
|
||||||
|
|
||||||
|
BIG_DECIMAL_LITERAL : FLOATING_POINT_NUMBER BIG_DECIMAL_SUFFIX;
|
||||||
|
|
||||||
|
HEX_LITERAL : '0' [xX] HEX_DIGIT+ LONG_SUFFIX?;
|
||||||
|
|
||||||
|
OCTAL_LITERAL : '0' ('0'..'7')+ ('l'|'L')? ;
|
||||||
|
|
||||||
|
STRING_LITERAL
|
||||||
|
: DOUBLE_QUOTE ( ~[\\"] | ESCAPE_SEQUENCE | DOUBLE_QUOTE DOUBLE_QUOTE )* DOUBLE_QUOTE
|
||||||
|
{ setText(getText().substring(1, getText().length()-1).replace("\"\"", "\"")); }
|
||||||
|
| SINGLE_QUOTE ( ~[\\'] | ESCAPE_SEQUENCE | SINGLE_QUOTE SINGLE_QUOTE )* SINGLE_QUOTE
|
||||||
|
{ setText(getText().substring(1, getText().length()-1).replace("''", "'")); }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
fragment
|
fragment
|
||||||
OCTAL_ESCAPE
|
OCTAL_ESCAPE
|
||||||
: '\\' ('0'..'3') ('0'..'7') ('0'..'7')
|
: '\\' ('0'..'3') ('0'..'7') ('0'..'7')
|
||||||
|
@ -72,10 +103,6 @@ OCTAL_ESCAPE
|
||||||
| '\\' ('0'..'7')
|
| '\\' ('0'..'7')
|
||||||
;
|
;
|
||||||
|
|
||||||
fragment
|
|
||||||
UNICODE_ESCAPE
|
|
||||||
: '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
|
|
||||||
;
|
|
||||||
|
|
||||||
// ESCAPE start tokens
|
// ESCAPE start tokens
|
||||||
TIMESTAMP_ESCAPE_START : '{ts';
|
TIMESTAMP_ESCAPE_START : '{ts';
|
||||||
|
@ -134,6 +161,7 @@ CONCAT : [cC] [oO] [nN] [cC] [aA] [tT];
|
||||||
COUNT : [cC] [oO] [uU] [nN] [tT];
|
COUNT : [cC] [oO] [uU] [nN] [tT];
|
||||||
CROSS : [cC] [rR] [oO] [sS] [sS];
|
CROSS : [cC] [rR] [oO] [sS] [sS];
|
||||||
CURRENT_DATE : [cC] [uU] [rR] [rR] [eE] [nN] [tT] '_' [dD] [aA] [tT] [eE];
|
CURRENT_DATE : [cC] [uU] [rR] [rR] [eE] [nN] [tT] '_' [dD] [aA] [tT] [eE];
|
||||||
|
CURRENT_DATETIME : [cC] [uU] [rR] [rR] [eE] [nN] [tT] '_' [dD] [aA] [tT] [eE] [tT] [iI] [mM] [eE];
|
||||||
CURRENT_INSTANT : [cC] [uU] [rR] [rR] [eE] [nN] [tT] '_' [iI] [nN] [sS] [tT] [aA] [nN] [tT];
|
CURRENT_INSTANT : [cC] [uU] [rR] [rR] [eE] [nN] [tT] '_' [iI] [nN] [sS] [tT] [aA] [nN] [tT];
|
||||||
CURRENT_TIME : [cC] [uU] [rR] [rR] [eE] [nN] [tT] '_' [tT] [iI] [mM] [eE];
|
CURRENT_TIME : [cC] [uU] [rR] [rR] [eE] [nN] [tT] '_' [tT] [iI] [mM] [eE];
|
||||||
CURRENT_TIMESTAMP : [cC] [uU] [rR] [rR] [eE] [nN] [tT] '_' [tT] [iI] [mM] [eE] [sS] [tT] [aA] [mM] [pP];
|
CURRENT_TIMESTAMP : [cC] [uU] [rR] [rR] [eE] [nN] [tT] '_' [tT] [iI] [mM] [eE] [sS] [tT] [aA] [mM] [pP];
|
||||||
|
@ -155,6 +183,7 @@ FETCH : [fF] [eE] [tT] [cC] [hH];
|
||||||
FLOOR : [fF] [lL] [oO] [oO] [rR];
|
FLOOR : [fF] [lL] [oO] [oO] [rR];
|
||||||
FROM : [fF] [rR] [oO] [mM];
|
FROM : [fF] [rR] [oO] [mM];
|
||||||
FOR : [fF] [oO] [rR];
|
FOR : [fF] [oO] [rR];
|
||||||
|
FORMAT : [fF] [oO] [rR] [mM] [aA] [tT];
|
||||||
FULL : [fF] [uU] [lL] [lL];
|
FULL : [fF] [uU] [lL] [lL];
|
||||||
FUNCTION : [fF] [uU] [nN] [cC] [tT] [iI] [oO] [nN];
|
FUNCTION : [fF] [uU] [nN] [cC] [tT] [iI] [oO] [nN];
|
||||||
GREATEST : [gG] [rR] [eE] [aA] [tT] [eE] [sS] [tT];
|
GREATEST : [gG] [rR] [eE] [aA] [tT] [eE] [sS] [tT];
|
||||||
|
|
|
@ -466,7 +466,6 @@ nullIf
|
||||||
|
|
||||||
literal
|
literal
|
||||||
: STRING_LITERAL
|
: STRING_LITERAL
|
||||||
| CHARACTER_LITERAL
|
|
||||||
| INTEGER_LITERAL
|
| INTEGER_LITERAL
|
||||||
| LONG_LITERAL
|
| LONG_LITERAL
|
||||||
| BIG_INTEGER_LITERAL
|
| BIG_INTEGER_LITERAL
|
||||||
|
@ -478,40 +477,79 @@ literal
|
||||||
| NULL
|
| NULL
|
||||||
| TRUE
|
| TRUE
|
||||||
| FALSE
|
| FALSE
|
||||||
| timestampLiteral
|
| temporalLiteral
|
||||||
| dateLiteral
|
| generalizedLiteral
|
||||||
| timeLiteral
|
|
||||||
;
|
;
|
||||||
|
|
||||||
// todo (6.0) : expand temporal literal support to Java 8 temporal types
|
temporalLiteral
|
||||||
// * Instant -> {instant '...'}
|
: dateTimeLiteral
|
||||||
// * LocalDate -> {localDate '...'}
|
| dateLiteral
|
||||||
// * LocalDateTime -> {localDateTime '...'}
|
| timeLiteral
|
||||||
// * OffsetDateTime -> {offsetDateTime '...'}
|
| jdbcTimestampLiteral
|
||||||
// * OffsetTime -> {offsetTime '...'}
|
| jdbcDateLiteral
|
||||||
// * ZonedDateTime -> {localDate '...'}
|
| jdbcTimeLiteral
|
||||||
// * ...
|
;
|
||||||
//
|
|
||||||
// Few things:
|
|
||||||
// 1) the markers above are just initial thoughts. They are obviously verbose. Maybe acronyms or shortened forms would be better
|
|
||||||
// 2) we may want to stay away from all of the timezone headaches by not supporting local, zoned and offset forms
|
|
||||||
|
|
||||||
timestampLiteral
|
dateTimeLiteral
|
||||||
: TIMESTAMP_ESCAPE_START dateTimeLiteralText RIGHT_BRACE
|
: LEFT_BRACE dateTime RIGHT_BRACE
|
||||||
;
|
;
|
||||||
|
|
||||||
dateLiteral
|
dateLiteral
|
||||||
: DATE_ESCAPE_START dateTimeLiteralText RIGHT_BRACE
|
: LEFT_BRACE date RIGHT_BRACE
|
||||||
;
|
;
|
||||||
|
|
||||||
timeLiteral
|
timeLiteral
|
||||||
: TIME_ESCAPE_START dateTimeLiteralText RIGHT_BRACE
|
: LEFT_BRACE time RIGHT_BRACE
|
||||||
;
|
;
|
||||||
|
|
||||||
dateTimeLiteralText
|
dateTime
|
||||||
: STRING_LITERAL | CHARACTER_LITERAL
|
: date time (zoneId | offset)?
|
||||||
;
|
;
|
||||||
|
|
||||||
|
date
|
||||||
|
: year MINUS month MINUS day
|
||||||
|
;
|
||||||
|
|
||||||
|
time
|
||||||
|
: hour COLON minute (COLON second)?
|
||||||
|
;
|
||||||
|
|
||||||
|
offset
|
||||||
|
: (PLUS | MINUS) hour (COLON minute)?
|
||||||
|
;
|
||||||
|
|
||||||
|
year: INTEGER_LITERAL;
|
||||||
|
month: INTEGER_LITERAL;
|
||||||
|
day: INTEGER_LITERAL;
|
||||||
|
hour: INTEGER_LITERAL;
|
||||||
|
minute: INTEGER_LITERAL;
|
||||||
|
second: INTEGER_LITERAL | FLOAT_LITERAL;
|
||||||
|
zoneId: STRING_LITERAL;
|
||||||
|
|
||||||
|
jdbcTimestampLiteral
|
||||||
|
: TIMESTAMP_ESCAPE_START (dateTime | genericTemporalLiteralText) RIGHT_BRACE
|
||||||
|
;
|
||||||
|
|
||||||
|
jdbcDateLiteral
|
||||||
|
: DATE_ESCAPE_START (date | genericTemporalLiteralText) RIGHT_BRACE
|
||||||
|
;
|
||||||
|
|
||||||
|
jdbcTimeLiteral
|
||||||
|
: TIME_ESCAPE_START (time | genericTemporalLiteralText) RIGHT_BRACE
|
||||||
|
;
|
||||||
|
|
||||||
|
genericTemporalLiteralText
|
||||||
|
: STRING_LITERAL
|
||||||
|
;
|
||||||
|
|
||||||
|
generalizedLiteral
|
||||||
|
: LEFT_BRACE generalizedLiteralType COLON generalizedLiteralText RIGHT_BRACE
|
||||||
|
;
|
||||||
|
|
||||||
|
generalizedLiteralType : STRING_LITERAL;
|
||||||
|
generalizedLiteralText : STRING_LITERAL;
|
||||||
|
|
||||||
|
|
||||||
parameter
|
parameter
|
||||||
: COLON identifier # NamedParameter
|
: COLON identifier # NamedParameter
|
||||||
| QUESTION_MARK INTEGER_LITERAL? # PositionalParameter
|
| QUESTION_MARK INTEGER_LITERAL? # PositionalParameter
|
||||||
|
@ -589,6 +627,7 @@ countFunction
|
||||||
standardFunction
|
standardFunction
|
||||||
: castFunction
|
: castFunction
|
||||||
| extractFunction
|
| extractFunction
|
||||||
|
| formatFunction
|
||||||
| concatFunction
|
| concatFunction
|
||||||
| substringFunction
|
| substringFunction
|
||||||
| replaceFunction
|
| replaceFunction
|
||||||
|
@ -666,7 +705,7 @@ trimSpecification
|
||||||
;
|
;
|
||||||
|
|
||||||
trimCharacter
|
trimCharacter
|
||||||
: CHARACTER_LITERAL | STRING_LITERAL
|
: STRING_LITERAL
|
||||||
;
|
;
|
||||||
|
|
||||||
upperFunction
|
upperFunction
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import java.time.temporal.TemporalAccessor;
|
import java.time.temporal.TemporalAccessor;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||||
import org.hibernate.dialect.function.H2ExtractEmulation;
|
import org.hibernate.dialect.function.H2ExtractEmulation;
|
||||||
|
import org.hibernate.dialect.function.Replacer;
|
||||||
import org.hibernate.dialect.hint.IndexQueryHintHandler;
|
import org.hibernate.dialect.hint.IndexQueryHintHandler;
|
||||||
import org.hibernate.dialect.identity.H2IdentityColumnSupport;
|
import org.hibernate.dialect.identity.H2IdentityColumnSupport;
|
||||||
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
||||||
|
@ -205,6 +206,19 @@ public class H2Dialect extends Dialect {
|
||||||
sqlAppender.append(")");
|
sqlAppender.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String translateExtractField(TemporalUnit unit) {
|
||||||
|
switch ( unit ) {
|
||||||
|
case DAY_OF_MONTH: return "day";
|
||||||
|
case WEEK: return "iso_week";
|
||||||
|
default: return unit.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String translateDatetimeFormat(String format) {
|
||||||
|
return new Replacer( format, "'", "''" ).replace( "e", "u").result(); //NICE!!
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAddColumnString() {
|
public String getAddColumnString() {
|
||||||
return "add column";
|
return "add column";
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Locale;
|
||||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||||
import org.hibernate.dialect.function.InformixExtractEmulation;
|
import org.hibernate.dialect.function.InformixExtractEmulation;
|
||||||
|
import org.hibernate.dialect.function.Replacer;
|
||||||
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
||||||
import org.hibernate.dialect.identity.InformixIdentityColumnSupport;
|
import org.hibernate.dialect.identity.InformixIdentityColumnSupport;
|
||||||
import org.hibernate.dialect.pagination.FirstLimitHandler;
|
import org.hibernate.dialect.pagination.FirstLimitHandler;
|
||||||
|
@ -117,6 +118,65 @@ public class InformixDialect extends Dialect {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String translateDatetimeFormat(String format) {
|
||||||
|
//Informix' own variation of MySQL
|
||||||
|
return datetimeFormat( format ).result();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Replacer datetimeFormat(String format) {
|
||||||
|
return new Replacer( format, "'", "" )
|
||||||
|
.replace("%", "%%")
|
||||||
|
|
||||||
|
//year
|
||||||
|
.replace("yyyy", "%Y")
|
||||||
|
.replace("yyy", "%Y")
|
||||||
|
.replace("yy", "%y")
|
||||||
|
.replace("y", "Y")
|
||||||
|
|
||||||
|
//month of year
|
||||||
|
.replace("MMMM", "%B")
|
||||||
|
.replace("MMM", "%b")
|
||||||
|
.replace("MM", "%m")
|
||||||
|
.replace("M", "%c") //????
|
||||||
|
|
||||||
|
//day of week
|
||||||
|
.replace("EEEE", "%A")
|
||||||
|
.replace("EEE", "%a")
|
||||||
|
.replace("ee", "%w")
|
||||||
|
.replace("e", "%w")
|
||||||
|
|
||||||
|
//day of month
|
||||||
|
.replace("dd", "%d")
|
||||||
|
.replace("d", "%e")
|
||||||
|
|
||||||
|
//am pm
|
||||||
|
.replace("aa", "%p") //?????
|
||||||
|
.replace("a", "%p") //?????
|
||||||
|
|
||||||
|
//hour
|
||||||
|
.replace("hh", "%I")
|
||||||
|
.replace("HH", "%H")
|
||||||
|
.replace("h", "%I")
|
||||||
|
.replace("H", "%H")
|
||||||
|
|
||||||
|
//minute
|
||||||
|
.replace("mm", "%M")
|
||||||
|
.replace("m", "%M")
|
||||||
|
|
||||||
|
//second
|
||||||
|
.replace("ss", "%S")
|
||||||
|
.replace("s", "%S")
|
||||||
|
|
||||||
|
//fractional seconds
|
||||||
|
.replace("SSSSSS", "%F50") //5 is the max
|
||||||
|
.replace("SSSSS", "%F5")
|
||||||
|
.replace("SSSS", "%F4")
|
||||||
|
.replace("SSS", "%F3")
|
||||||
|
.replace("SS", "%F2")
|
||||||
|
.replace("S", "%F1");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAddColumnString() {
|
public String getAddColumnString() {
|
||||||
return "add";
|
return "add";
|
||||||
|
|
|
@ -188,6 +188,22 @@ public class IngresDialect extends Dialect {
|
||||||
sqlAppender.append(")");
|
sqlAppender.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String translateDatetimeFormat(String format) {
|
||||||
|
return MySQLDialect.datetimeFormat( format ).result();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String translateExtractField(TemporalUnit unit) {
|
||||||
|
switch ( unit ) {
|
||||||
|
case DAY_OF_MONTH: return "day";
|
||||||
|
case DAY_OF_YEAR: return "doy";
|
||||||
|
case DAY_OF_WEEK: return "dow";
|
||||||
|
case WEEK: return "iso_week";
|
||||||
|
default: return unit.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSelectGUIDString() {
|
public String getSelectGUIDString() {
|
||||||
return "select uuid_to_char(uuid_create())";
|
return "select uuid_to_char(uuid_create())";
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||||
import org.hibernate.dialect.function.MySQLExtractEmulation;
|
import org.hibernate.dialect.function.MySQLExtractEmulation;
|
||||||
|
import org.hibernate.dialect.function.Replacer;
|
||||||
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
||||||
import org.hibernate.dialect.identity.MySQLIdentityColumnSupport;
|
import org.hibernate.dialect.identity.MySQLIdentityColumnSupport;
|
||||||
import org.hibernate.dialect.pagination.AbstractLimitHandler;
|
import org.hibernate.dialect.pagination.AbstractLimitHandler;
|
||||||
|
@ -242,6 +243,80 @@ public class MySQLDialect extends Dialect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String translateDatetimeFormat(String format) {
|
||||||
|
return datetimeFormat( format ).result();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Replacer datetimeFormat(String format) {
|
||||||
|
return new Replacer( format, "'", "" )
|
||||||
|
.replace("%", "%%")
|
||||||
|
|
||||||
|
//year
|
||||||
|
.replace("yyyy", "%Y")
|
||||||
|
.replace("yyy", "%Y")
|
||||||
|
.replace("yy", "%y")
|
||||||
|
.replace("y", "%Y")
|
||||||
|
|
||||||
|
//month of year
|
||||||
|
.replace("MMMM", "%M")
|
||||||
|
.replace("MMM", "%b")
|
||||||
|
.replace("MM", "%m")
|
||||||
|
.replace("M", "%c")
|
||||||
|
|
||||||
|
//week of year
|
||||||
|
.replace("ww", "%v")
|
||||||
|
.replace("w", "%v")
|
||||||
|
//year for week
|
||||||
|
.replace("YYYY", "%x")
|
||||||
|
.replace("YYY", "%x")
|
||||||
|
.replace("Y", "%x")
|
||||||
|
|
||||||
|
//week of month
|
||||||
|
//????
|
||||||
|
|
||||||
|
//day of week
|
||||||
|
.replace("EEEE", "%W")
|
||||||
|
.replace("EEE", "%a")
|
||||||
|
.replace("ee", "%w")
|
||||||
|
.replace("e", "%w")
|
||||||
|
|
||||||
|
//day of month
|
||||||
|
.replace("dd", "%d")
|
||||||
|
.replace("d", "%e")
|
||||||
|
|
||||||
|
//day of year
|
||||||
|
.replace("DDD", "%j")
|
||||||
|
.replace("DD", "%j")
|
||||||
|
.replace("D", "%j")
|
||||||
|
|
||||||
|
//am pm
|
||||||
|
.replace("aa", "%p")
|
||||||
|
.replace("a", "%p")
|
||||||
|
|
||||||
|
//hour
|
||||||
|
.replace("hh", "%h")
|
||||||
|
.replace("HH", "%H")
|
||||||
|
.replace("h", "%l")
|
||||||
|
.replace("H", "%k")
|
||||||
|
|
||||||
|
//minute
|
||||||
|
.replace("mm", "%i")
|
||||||
|
.replace("m", "%i")
|
||||||
|
|
||||||
|
//second
|
||||||
|
.replace("ss", "%S")
|
||||||
|
.replace("s", "%S")
|
||||||
|
|
||||||
|
//fractional seconds
|
||||||
|
.replace("SSSSSS", "%f")
|
||||||
|
.replace("SSSSS", "%f")
|
||||||
|
.replace("SSSS", "%f")
|
||||||
|
.replace("SSS", "%f")
|
||||||
|
.replace("SS", "%f")
|
||||||
|
.replace("S", "%f");
|
||||||
|
}
|
||||||
|
|
||||||
void upgradeTo57() {
|
void upgradeTo57() {
|
||||||
|
|
||||||
// For details about MySQL 5.7 support for fractional seconds
|
// For details about MySQL 5.7 support for fractional seconds
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||||
import org.hibernate.dialect.function.NvlCoalesceEmulation;
|
import org.hibernate.dialect.function.NvlCoalesceEmulation;
|
||||||
import org.hibernate.dialect.function.OracleExtractEmulation;
|
import org.hibernate.dialect.function.OracleExtractEmulation;
|
||||||
|
import org.hibernate.dialect.function.Replacer;
|
||||||
import org.hibernate.dialect.pagination.AbstractLimitHandler;
|
import org.hibernate.dialect.pagination.AbstractLimitHandler;
|
||||||
import org.hibernate.dialect.pagination.LimitHandler;
|
import org.hibernate.dialect.pagination.LimitHandler;
|
||||||
import org.hibernate.dialect.pagination.LimitHelper;
|
import org.hibernate.dialect.pagination.LimitHelper;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||||
import org.hibernate.dialect.function.PostgresExtractEmulation;
|
import org.hibernate.dialect.function.PostgresExtractEmulation;
|
||||||
|
import org.hibernate.dialect.function.Replacer;
|
||||||
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
||||||
import org.hibernate.dialect.identity.PostgreSQL81IdentityColumnSupport;
|
import org.hibernate.dialect.identity.PostgreSQL81IdentityColumnSupport;
|
||||||
import org.hibernate.dialect.pagination.AbstractLimitHandler;
|
import org.hibernate.dialect.pagination.AbstractLimitHandler;
|
||||||
|
|
|
@ -12,12 +12,14 @@ import java.util.Locale;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||||
|
import org.hibernate.dialect.function.Replacer;
|
||||||
import org.hibernate.dialect.function.TransactSQLTrimEmulation;
|
import org.hibernate.dialect.function.TransactSQLTrimEmulation;
|
||||||
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
||||||
import org.hibernate.dialect.identity.SQLServerIdentityColumnSupport;
|
import org.hibernate.dialect.identity.SQLServerIdentityColumnSupport;
|
||||||
import org.hibernate.dialect.pagination.LegacyLimitHandler;
|
import org.hibernate.dialect.pagination.LegacyLimitHandler;
|
||||||
import org.hibernate.dialect.pagination.LimitHandler;
|
import org.hibernate.dialect.pagination.LimitHandler;
|
||||||
import org.hibernate.dialect.pagination.TopLimitHandler;
|
import org.hibernate.dialect.pagination.TopLimitHandler;
|
||||||
|
import org.hibernate.query.TemporalUnit;
|
||||||
import org.hibernate.query.spi.QueryEngine;
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
import org.hibernate.type.descriptor.sql.SmallIntTypeDescriptor;
|
import org.hibernate.type.descriptor.sql.SmallIntTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||||
|
@ -59,6 +61,58 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
||||||
queryEngine.getSqmFunctionRegistry().register( "trim", new TransactSQLTrimEmulation() );
|
queryEngine.getSqmFunctionRegistry().register( "trim", new TransactSQLTrimEmulation() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String translateExtractField(TemporalUnit unit) {
|
||||||
|
switch ( unit ) {
|
||||||
|
case WEEK: return "isowk"; //the ISO week number (behavior of "week" depends on a system property)
|
||||||
|
default: return super.translateExtractField(unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String translateDatetimeFormat(String format) {
|
||||||
|
return datetimeFormat(format).result();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Replacer datetimeFormat(String format) {
|
||||||
|
return new Replacer( format, "'", "\"" )
|
||||||
|
//era
|
||||||
|
.replace("G", "g")
|
||||||
|
|
||||||
|
//y nothing to do
|
||||||
|
//M nothing to do
|
||||||
|
|
||||||
|
//w no equivalent
|
||||||
|
//W no equivalent
|
||||||
|
//Y no equivalent
|
||||||
|
|
||||||
|
//day of week
|
||||||
|
.replace("EEEE", "dddd")
|
||||||
|
.replace("EEE", "ddd")
|
||||||
|
//e no equivalent
|
||||||
|
|
||||||
|
//d nothing to do
|
||||||
|
//D no equivalent
|
||||||
|
|
||||||
|
//am pm
|
||||||
|
.replace("aa", "tt")
|
||||||
|
.replace("a", "tt")
|
||||||
|
|
||||||
|
//h nothing to do
|
||||||
|
//H nothing to do
|
||||||
|
|
||||||
|
//m nothing to do
|
||||||
|
//s nothing to do
|
||||||
|
|
||||||
|
//fractional seconds
|
||||||
|
.replace("S", "F")
|
||||||
|
|
||||||
|
//timezones
|
||||||
|
.replace("XXX", "K") //UTC represented as "Z"
|
||||||
|
.replace("xxx", "zzz")
|
||||||
|
.replace("x", "zz");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNoColumnsInsertString() {
|
public String getNoColumnsInsertString() {
|
||||||
return "default values";
|
return "default values";
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
package org.hibernate.dialect.function;
|
package org.hibernate.dialect.function;
|
||||||
|
|
||||||
import org.hibernate.query.spi.QueryEngine;
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
import org.hibernate.query.sqm.function.StandardFunctionRenderingSupport;
|
|
||||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
|
|
@ -4,21 +4,24 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect.function;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.Internal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
|
@Internal
|
||||||
public class Replacer {
|
public class Replacer {
|
||||||
private String[] chunks;
|
private String[] chunks;
|
||||||
private String quote;
|
private String quote;
|
||||||
private String delimiter;
|
private String delimiter;
|
||||||
private List<Replacement> replacements = new ArrayList<>();
|
private List<Replacement> replacements = new ArrayList<>();
|
||||||
|
|
||||||
class Replacement {
|
public static class Replacement {
|
||||||
String placeholder;
|
String placeholder;
|
||||||
String replacement;
|
String replacement;
|
||||||
|
|
||||||
|
@ -45,7 +48,7 @@ public class Replacer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Replacer(String format, String quote, String delimiter) {
|
public Replacer(String format, String quote, String delimiter) {
|
||||||
this.delimiter = delimiter;
|
this.delimiter = delimiter;
|
||||||
this.chunks = format.split( quote );
|
this.chunks = format.split( quote );
|
||||||
this.quote = quote;
|
this.quote = quote;
|
|
@ -157,7 +157,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
private final boolean[] isNullableTable;
|
private final boolean[] isNullableTable;
|
||||||
private final boolean[] isInverseTable;
|
private final boolean[] isInverseTable;
|
||||||
|
|
||||||
private final Map<String, String> discriminatorValuesByTableName;
|
private final Map<String, Object> discriminatorValuesByTableName;
|
||||||
private final Map<String, String> subclassNameByTableName;
|
private final Map<String, String> subclassNameByTableName;
|
||||||
|
|
||||||
//INITIALIZATION:
|
//INITIALIZATION:
|
||||||
|
@ -532,7 +532,22 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
|
|
||||||
discriminatorValuesByTableName = new LinkedHashMap<>( subclassSpan + 1 );
|
discriminatorValuesByTableName = new LinkedHashMap<>( subclassSpan + 1 );
|
||||||
subclassNameByTableName = new HashMap<>( subclassSpan + 1);
|
subclassNameByTableName = new HashMap<>( subclassSpan + 1);
|
||||||
discriminatorValuesByTableName.put( persistentClass.getTable().getName(), discriminatorSQLString);
|
// We need to convert the `discriminatorSQLString` (which is a String read from boot-mapping) into
|
||||||
|
// the type indicated by `#discriminatorType` (String -> Integer, e.g.).
|
||||||
|
try {
|
||||||
|
final Object convertedDiscriminatorValue = discriminatorType.stringToObject( discriminatorSQLString );
|
||||||
|
discriminatorValuesByTableName.put( persistentClass.getTable().getName(), convertedDiscriminatorValue );
|
||||||
|
}
|
||||||
|
catch (HibernateException e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new MappingException(
|
||||||
|
"Could not resolve specified discriminator value [" + discriminatorSQLString
|
||||||
|
+ "] to discriminator type [" + discriminatorType + "]"
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
discriminatorValues = new String[subclassSpan];
|
discriminatorValues = new String[subclassSpan];
|
||||||
discriminatorValues[subclassSpan - 1] = discriminatorSQLString;
|
discriminatorValues[subclassSpan - 1] = discriminatorSQLString;
|
||||||
notNullColumnTableNumbers = new int[subclassSpan];
|
notNullColumnTableNumbers = new int[subclassSpan];
|
||||||
|
@ -590,7 +605,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
// "foo.class = Bar" works in HQL
|
// "foo.class = Bar" works in HQL
|
||||||
discriminatorValue = sc.getSubclassId();
|
discriminatorValue = sc.getSubclassId();
|
||||||
}
|
}
|
||||||
discriminatorValuesByTableName.put( sc.getTable().getName(), discriminatorValue.toString() );
|
discriminatorValuesByTableName.put( sc.getTable().getName(), discriminatorValue );
|
||||||
subclassesByDiscriminatorValue.put( discriminatorValue, sc.getEntityName() );
|
subclassesByDiscriminatorValue.put( discriminatorValue, sc.getEntityName() );
|
||||||
discriminatorValues[k] = discriminatorValue.toString();
|
discriminatorValues[k] = discriminatorValue.toString();
|
||||||
int id = getTableId(
|
int id = getTableId(
|
||||||
|
@ -1320,8 +1335,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
ColumnReference identifierColumnReference,
|
ColumnReference identifierColumnReference,
|
||||||
BasicType resultType) {
|
BasicType resultType) {
|
||||||
final Predicate predicate = new NullnessPredicate( identifierColumnReference, true );
|
final Predicate predicate = new NullnessPredicate( identifierColumnReference, true );
|
||||||
final Expression expression =
|
final Expression expression = new QueryLiteral<>(
|
||||||
new QueryLiteral<>(
|
|
||||||
discriminatorValuesByTableName.get( table.getTableExpression() ),
|
discriminatorValuesByTableName.get( table.getTableExpression() ),
|
||||||
resultType
|
resultType
|
||||||
);
|
);
|
||||||
|
|
|
@ -103,7 +103,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
private final int[] subclassFormulaTableNumberClosure;
|
private final int[] subclassFormulaTableNumberClosure;
|
||||||
|
|
||||||
// discriminator column
|
// discriminator column
|
||||||
private final Map<Object, String> subclassesByDiscriminatorValue = new HashMap<Object, String>();
|
private final Map<Object, String> subclassesByDiscriminatorValue = new HashMap<>();
|
||||||
private final boolean forceDiscriminator;
|
private final boolean forceDiscriminator;
|
||||||
private final String discriminatorColumnName;
|
private final String discriminatorColumnName;
|
||||||
private final String discriminatorColumnReaders;
|
private final String discriminatorColumnReaders;
|
||||||
|
|
|
@ -36,6 +36,9 @@ public enum QueryLiteralRendering {
|
||||||
/**
|
/**
|
||||||
* As a parameter when the literal occurs outside the SELECT clause,
|
* As a parameter when the literal occurs outside the SELECT clause,
|
||||||
* otherwise render as a SQL literal.
|
* otherwise render as a SQL literal.
|
||||||
|
*
|
||||||
|
* Technically this should be called something like AS_PARAM_UNLESS_SELECTED. If the literal is used as an argument
|
||||||
|
* to a function call in the select-clause, for example, we'd still want to render as a parameter.
|
||||||
*/
|
*/
|
||||||
AS_PARAM_OUTSIDE_SELECT( "param-outside-select" );
|
AS_PARAM_OUTSIDE_SELECT( "param-outside-select" );
|
||||||
|
|
||||||
|
|
|
@ -12,13 +12,19 @@ import java.sql.Date;
|
||||||
import java.sql.Time;
|
import java.sql.Time;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.temporal.TemporalAccessor;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.NullPrecedence;
|
import org.hibernate.NullPrecedence;
|
||||||
|
@ -30,6 +36,7 @@ import org.hibernate.grammars.hql.HqlParserBaseVisitor;
|
||||||
import org.hibernate.internal.util.collections.Stack;
|
import org.hibernate.internal.util.collections.Stack;
|
||||||
import org.hibernate.internal.util.collections.StandardStack;
|
import org.hibernate.internal.util.collections.StandardStack;
|
||||||
import org.hibernate.metamodel.CollectionClassification;
|
import org.hibernate.metamodel.CollectionClassification;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
|
@ -67,6 +74,7 @@ import org.hibernate.query.sqm.internal.SqmDmlCreationProcessingState;
|
||||||
import org.hibernate.query.sqm.internal.SqmQuerySpecCreationProcessingStateStandardImpl;
|
import org.hibernate.query.sqm.internal.SqmQuerySpecCreationProcessingStateStandardImpl;
|
||||||
import org.hibernate.query.sqm.spi.ParameterDeclarationContext;
|
import org.hibernate.query.sqm.spi.ParameterDeclarationContext;
|
||||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||||
|
@ -80,7 +88,6 @@ import org.hibernate.query.sqm.tree.domain.SqmMinIndexPath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
||||||
import org.hibernate.query.sqm.tree.expression.LiteralHelper;
|
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmBinaryArithmetic;
|
import org.hibernate.query.sqm.tree.expression.SqmBinaryArithmetic;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
|
import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
|
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
|
||||||
|
@ -89,6 +96,7 @@ import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
|
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
|
||||||
|
@ -97,6 +105,7 @@ import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmPathEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmPathEntityType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmSelfRenderingExpression;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmStar;
|
import org.hibernate.query.sqm.tree.expression.SqmStar;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
|
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation;
|
import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation;
|
||||||
|
@ -136,7 +145,9 @@ import org.hibernate.query.sqm.tree.select.SqmSelection;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSortSpecification;
|
import org.hibernate.query.sqm.tree.select.SqmSortSpecification;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||||
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
import org.hibernate.type.descriptor.DateTimeUtils;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
@ -150,6 +161,7 @@ import static org.hibernate.query.TemporalUnit.DAY_OF_MONTH;
|
||||||
import static org.hibernate.query.TemporalUnit.DAY_OF_WEEK;
|
import static org.hibernate.query.TemporalUnit.DAY_OF_WEEK;
|
||||||
import static org.hibernate.query.TemporalUnit.DAY_OF_YEAR;
|
import static org.hibernate.query.TemporalUnit.DAY_OF_YEAR;
|
||||||
import static org.hibernate.query.TemporalUnit.OFFSET;
|
import static org.hibernate.query.TemporalUnit.OFFSET;
|
||||||
|
import static org.hibernate.query.TemporalUnit.SECOND;
|
||||||
import static org.hibernate.query.TemporalUnit.TIME;
|
import static org.hibernate.query.TemporalUnit.TIME;
|
||||||
import static org.hibernate.query.TemporalUnit.TIMEZONE_HOUR;
|
import static org.hibernate.query.TemporalUnit.TIMEZONE_HOUR;
|
||||||
import static org.hibernate.query.TemporalUnit.TIMEZONE_MINUTE;
|
import static org.hibernate.query.TemporalUnit.TIMEZONE_MINUTE;
|
||||||
|
@ -171,6 +183,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
* Main entry point into analysis of HQL/JPQL parse tree - producing a semantic model of the
|
* Main entry point into analysis of HQL/JPQL parse tree - producing a semantic model of the
|
||||||
* query.
|
* query.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
public static SqmStatement buildSemanticModel(
|
public static SqmStatement buildSemanticModel(
|
||||||
HqlParser.StatementContext hqlParseTree,
|
HqlParser.StatementContext hqlParseTree,
|
||||||
SqmCreationOptions creationOptions,
|
SqmCreationOptions creationOptions,
|
||||||
|
@ -195,6 +208,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
return processingStateStack;
|
return processingStateStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
public SemanticQueryBuilder(SqmCreationOptions creationOptions, SqmCreationContext creationContext) {
|
public SemanticQueryBuilder(SqmCreationOptions creationOptions, SqmCreationContext creationContext) {
|
||||||
this.creationOptions = creationOptions;
|
this.creationOptions = creationOptions;
|
||||||
this.creationContext = creationContext;
|
this.creationContext = creationContext;
|
||||||
|
@ -1408,7 +1422,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
return new SqmFunction(
|
return new SqmFunction(
|
||||||
"mod",
|
"mod",
|
||||||
getFunctionDescriptor( "mod" ),
|
getFunctionDescriptor( "mod" ),
|
||||||
(AllowableFunctionReturnType) dividend.getNodeType(),
|
dividend.getNodeType(),
|
||||||
asList( dividend, divisor ),
|
asList( dividend, divisor ),
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
|
@ -1513,7 +1527,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
return new SqmFunction(
|
return new SqmFunction(
|
||||||
"local_datetime",
|
"local_datetime",
|
||||||
getFunctionDescriptor( "local_datetime" ),
|
getFunctionDescriptor( "local_datetime" ),
|
||||||
StandardBasicTypes.TIMESTAMP,
|
StandardBasicTypes.LOCAL_DATE_TIME,
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1524,7 +1538,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
return new SqmFunction(
|
return new SqmFunction(
|
||||||
"local_date",
|
"local_date",
|
||||||
getFunctionDescriptor( "local_date" ),
|
getFunctionDescriptor( "local_date" ),
|
||||||
StandardBasicTypes.TIMESTAMP,
|
StandardBasicTypes.LOCAL_DATE,
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1535,7 +1549,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
return new SqmFunction(
|
return new SqmFunction(
|
||||||
"local_time",
|
"local_time",
|
||||||
getFunctionDescriptor( "local_time" ),
|
getFunctionDescriptor( "local_time" ),
|
||||||
StandardBasicTypes.TIMESTAMP,
|
StandardBasicTypes.LOCAL_TIME,
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1568,7 +1582,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
return new SqmFunction(
|
return new SqmFunction(
|
||||||
"least",
|
"least",
|
||||||
getFunctionDescriptor( "least" ),
|
getFunctionDescriptor( "least" ),
|
||||||
(AllowableFunctionReturnType<?>) type,
|
type,
|
||||||
arguments,
|
arguments,
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
|
@ -1637,22 +1651,23 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmLiteral visitLiteralExpression(HqlParser.LiteralExpressionContext ctx) {
|
public SqmLiteral visitLiteralExpression(HqlParser.LiteralExpressionContext ctx) {
|
||||||
if ( ctx.literal().CHARACTER_LITERAL() != null ) {
|
if ( ctx.literal().STRING_LITERAL() != null ) {
|
||||||
return characterLiteral( ctx.literal().CHARACTER_LITERAL().getText() );
|
|
||||||
}
|
|
||||||
else if ( ctx.literal().STRING_LITERAL() != null ) {
|
|
||||||
return stringLiteral( ctx.literal().STRING_LITERAL().getText() );
|
return stringLiteral( ctx.literal().STRING_LITERAL().getText() );
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().INTEGER_LITERAL() != null ) {
|
|
||||||
|
if ( ctx.literal().INTEGER_LITERAL() != null ) {
|
||||||
return integerLiteral( ctx.literal().INTEGER_LITERAL().getText() );
|
return integerLiteral( ctx.literal().INTEGER_LITERAL().getText() );
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().LONG_LITERAL() != null ) {
|
|
||||||
|
if ( ctx.literal().LONG_LITERAL() != null ) {
|
||||||
return longLiteral( ctx.literal().LONG_LITERAL().getText() );
|
return longLiteral( ctx.literal().LONG_LITERAL().getText() );
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().BIG_INTEGER_LITERAL() != null ) {
|
|
||||||
|
if ( ctx.literal().BIG_INTEGER_LITERAL() != null ) {
|
||||||
return bigIntegerLiteral( ctx.literal().BIG_INTEGER_LITERAL().getText() );
|
return bigIntegerLiteral( ctx.literal().BIG_INTEGER_LITERAL().getText() );
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().HEX_LITERAL() != null ) {
|
|
||||||
|
if ( ctx.literal().HEX_LITERAL() != null ) {
|
||||||
final String text = ctx.literal().HEX_LITERAL().getText();
|
final String text = ctx.literal().HEX_LITERAL().getText();
|
||||||
if ( text.endsWith( "l" ) || text.endsWith( "L" ) ) {
|
if ( text.endsWith( "l" ) || text.endsWith( "L" ) ) {
|
||||||
return longLiteral( text );
|
return longLiteral( text );
|
||||||
|
@ -1661,7 +1676,8 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
return integerLiteral( text );
|
return integerLiteral( text );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().OCTAL_LITERAL() != null ) {
|
|
||||||
|
if ( ctx.literal().OCTAL_LITERAL() != null ) {
|
||||||
final String text = ctx.literal().OCTAL_LITERAL().getText();
|
final String text = ctx.literal().OCTAL_LITERAL().getText();
|
||||||
if ( text.endsWith( "l" ) || text.endsWith( "L" ) ) {
|
if ( text.endsWith( "l" ) || text.endsWith( "L" ) ) {
|
||||||
return longLiteral( text );
|
return longLiteral( text );
|
||||||
|
@ -1670,56 +1686,379 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
return integerLiteral( text );
|
return integerLiteral( text );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().FLOAT_LITERAL() != null ) {
|
|
||||||
|
if ( ctx.literal().FLOAT_LITERAL() != null ) {
|
||||||
return floatLiteral( ctx.literal().FLOAT_LITERAL().getText() );
|
return floatLiteral( ctx.literal().FLOAT_LITERAL().getText() );
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().DOUBLE_LITERAL() != null ) {
|
|
||||||
|
if ( ctx.literal().DOUBLE_LITERAL() != null ) {
|
||||||
return doubleLiteral( ctx.literal().DOUBLE_LITERAL().getText() );
|
return doubleLiteral( ctx.literal().DOUBLE_LITERAL().getText() );
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().BIG_DECIMAL_LITERAL() != null ) {
|
|
||||||
|
if ( ctx.literal().BIG_DECIMAL_LITERAL() != null ) {
|
||||||
return bigDecimalLiteral( ctx.literal().BIG_DECIMAL_LITERAL().getText() );
|
return bigDecimalLiteral( ctx.literal().BIG_DECIMAL_LITERAL().getText() );
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().FALSE() != null ) {
|
|
||||||
|
if ( ctx.literal().FALSE() != null ) {
|
||||||
return booleanLiteral( false );
|
return booleanLiteral( false );
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().TRUE() != null ) {
|
|
||||||
|
if ( ctx.literal().TRUE() != null ) {
|
||||||
return booleanLiteral( true );
|
return booleanLiteral( true );
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().NULL() != null ) {
|
|
||||||
|
if ( ctx.literal().NULL() != null ) {
|
||||||
return new SqmLiteralNull( creationContext.getQueryEngine().getCriteriaBuilder() );
|
return new SqmLiteralNull( creationContext.getQueryEngine().getCriteriaBuilder() );
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().timestampLiteral() != null ) {
|
|
||||||
return LiteralHelper.timestampLiteralFrom( ctx.literal().timestampLiteral().dateTimeLiteralText().getText(), this );
|
if ( ctx.literal().temporalLiteral() != null ) {
|
||||||
|
return interpretTemporalLiteral( ctx.literal().temporalLiteral() );
|
||||||
}
|
}
|
||||||
else if ( ctx.literal().dateLiteral() != null ) {
|
|
||||||
return LiteralHelper.dateLiteralFrom( ctx.literal().dateLiteral().dateTimeLiteralText().getText(), this );
|
if ( ctx.literal().generalizedLiteral() != null ) {
|
||||||
}
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
else if ( ctx.literal().timeLiteral() != null ) {
|
|
||||||
return LiteralHelper.timeLiteralFrom( ctx.literal().timeLiteral().dateTimeLiteralText().getText(), this );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise we have a problem
|
// otherwise we have a problem
|
||||||
throw new ParsingException( "Unexpected literal expression type [" + ctx.getText() + "]" );
|
throw new ParsingException( "Unexpected literal expression type [" + ctx.getText() + "]" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SqmLiteral interpretTemporalLiteral(HqlParser.TemporalLiteralContext temporalLiteral) {
|
||||||
|
if ( temporalLiteral.dateTimeLiteral() != null ) {
|
||||||
|
return interpretDateTimeLiteral( temporalLiteral.dateTimeLiteral() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( temporalLiteral.dateLiteral() != null ) {
|
||||||
|
return interpretDateLiteral( temporalLiteral.dateLiteral() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( temporalLiteral.timeLiteral() != null ) {
|
||||||
|
return interpretTimeLiteral( temporalLiteral.timeLiteral() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( temporalLiteral.jdbcTimestampLiteral() != null ) {
|
||||||
|
return interpretJdbcDateTimeLiteral( temporalLiteral.jdbcTimestampLiteral() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( temporalLiteral.jdbcDateLiteral() != null ) {
|
||||||
|
return interpretJdbcDateLiteral( temporalLiteral.jdbcDateLiteral() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( temporalLiteral.jdbcTimeLiteral() != null ) {
|
||||||
|
return interpretJdbcTimeLiteral( temporalLiteral.jdbcTimeLiteral() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise we have a problem
|
||||||
|
throw new ParsingException( "Could not interpret temporal literal expression [" + temporalLiteral.getText() + "]" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmLiteral interpretDateTimeLiteral(HqlParser.DateTimeLiteralContext dateTimeLiteral) {
|
||||||
|
final HqlParser.DateTimeContext dateTimeCtx = dateTimeLiteral.dateTime();
|
||||||
|
|
||||||
|
final HqlParser.DateContext dateCtx = dateTimeCtx.date();
|
||||||
|
final HqlParser.TimeContext timeCtx = dateTimeCtx.time();
|
||||||
|
|
||||||
|
final LocalDate localDate = localDate( dateCtx );
|
||||||
|
final LocalTime localTime = localTime( timeCtx );
|
||||||
|
|
||||||
|
if ( dateTimeCtx.zoneId() == null && dateTimeCtx.offset() == null ) {
|
||||||
|
return new SqmLiteral<>(
|
||||||
|
LocalDateTime.of( localDate, localTime ),
|
||||||
|
basicType( LocalDateTime.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dateTimeCtx.zoneId() != null ) {
|
||||||
|
// we have a "zone id", which could still identify an offset rather that a ZoneId
|
||||||
|
try {
|
||||||
|
//noinspection unchecked
|
||||||
|
return new SqmLiteral(
|
||||||
|
ZonedDateTime.of(
|
||||||
|
localDate,
|
||||||
|
localTime,
|
||||||
|
ZoneId.of( dateTimeCtx.zoneId().STRING_LITERAL().getText() )
|
||||||
|
),
|
||||||
|
basicType( OffsetDateTime.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return new SqmLiteral(
|
||||||
|
ZonedDateTime.of(
|
||||||
|
localDate,
|
||||||
|
localTime,
|
||||||
|
TimeZone.getTimeZone( dateTimeCtx.zoneId().STRING_LITERAL().getText() ).toZoneId()
|
||||||
|
),
|
||||||
|
basicType( ZonedDateTime.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final HqlParser.OffsetContext offsetCtx = dateTimeCtx.offset();
|
||||||
|
assert offsetCtx != null;
|
||||||
|
|
||||||
|
// handle the offset
|
||||||
|
final int hourCtx = Integer.parseInt( offsetCtx.hour().INTEGER_LITERAL().getText() );
|
||||||
|
final int hour = offsetCtx.MINUS() == null
|
||||||
|
? hourCtx
|
||||||
|
: 0 - hourCtx;
|
||||||
|
final ZoneOffset offset = ZoneOffset.ofHoursMinutes(
|
||||||
|
hour,
|
||||||
|
offsetCtx.minute() == null
|
||||||
|
? 0
|
||||||
|
: Integer.parseInt( offsetCtx.minute().INTEGER_LITERAL().getText() )
|
||||||
|
);
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
return new SqmLiteral(
|
||||||
|
OffsetDateTime.of( localDate, localTime, offset ),
|
||||||
|
basicType( OffsetDateTime.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmLiteral interpretJdbcDateTimeLiteral(HqlParser.JdbcTimestampLiteralContext jdbcDateTimeLiteralCtx) {
|
||||||
|
final Timestamp timestamp;
|
||||||
|
|
||||||
|
if ( jdbcDateTimeLiteralCtx.genericTemporalLiteralText() != null ) {
|
||||||
|
final TemporalAccessor parsed = DateTimeUtils.DATE_TIME.parseBest(
|
||||||
|
jdbcDateTimeLiteralCtx.genericTemporalLiteralText().STRING_LITERAL().getText(),
|
||||||
|
OffsetDateTime::from,
|
||||||
|
ZonedDateTime::from,
|
||||||
|
LocalDateTime::from
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( parsed instanceof LocalDateTime ) {
|
||||||
|
final LocalDateTime localDateTime = (LocalDateTime) parsed;
|
||||||
|
|
||||||
|
//noinspection deprecation
|
||||||
|
timestamp = new Timestamp(
|
||||||
|
localDateTime.getYear(),
|
||||||
|
localDateTime.getMonthValue(),
|
||||||
|
localDateTime.getDayOfMonth(),
|
||||||
|
localDateTime.getHour(),
|
||||||
|
localDateTime.getMinute(),
|
||||||
|
localDateTime.getSecond(),
|
||||||
|
localDateTime.getNano()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ( parsed instanceof OffsetDateTime ) {
|
||||||
|
timestamp = new Timestamp( ( (OffsetDateTime) parsed ).toInstant().toEpochMilli() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert parsed instanceof ZonedDateTime;
|
||||||
|
timestamp = new Timestamp( ( (ZonedDateTime) parsed ).toInstant().toEpochMilli() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final HqlParser.DateTimeContext dateTimeCtx = jdbcDateTimeLiteralCtx.dateTime();
|
||||||
|
assert dateTimeCtx != null;
|
||||||
|
|
||||||
|
final LocalDateTime localDateTime = LocalDateTime.of(
|
||||||
|
localDate( dateTimeCtx.date() ),
|
||||||
|
localTime( dateTimeCtx.time() )
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( dateTimeCtx.zoneId() == null && dateTimeCtx.offset() == null ) {
|
||||||
|
// todo (6.0) : use local-tz or jdbc-tz as offset?
|
||||||
|
// for now, just use UTC
|
||||||
|
|
||||||
|
timestamp = new Timestamp( localDateTime.toInstant( ZoneOffset.UTC ).toEpochMilli() );
|
||||||
|
|
||||||
|
// below is another option
|
||||||
|
// timestamp = new Timestamp(
|
||||||
|
// localDateTime.getYear(),
|
||||||
|
// localDateTime.getMonthValue(),
|
||||||
|
// localDateTime.getDayOfMonth(),
|
||||||
|
// localDateTime.getHour(),
|
||||||
|
// localDateTime.getMinute(),
|
||||||
|
// localDateTime.getSecond(),
|
||||||
|
// localDateTime.getNano()
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
else if ( dateTimeCtx.zoneId() != null ) {
|
||||||
|
// we have a "zone id", which could still identify an offset rather that a ZoneId
|
||||||
|
ZoneId zoneId;
|
||||||
|
try {
|
||||||
|
zoneId = ZoneId.of( dateTimeCtx.zoneId().STRING_LITERAL().getText() );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
zoneId = TimeZone.getTimeZone( dateTimeCtx.zoneId().STRING_LITERAL().getText() ).toZoneId();
|
||||||
|
//noinspection unchecked
|
||||||
|
return new SqmLiteral(
|
||||||
|
ZonedDateTime.of( localDateTime, zoneId ),
|
||||||
|
basicType( OffsetDateTime.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp = new Timestamp( ZonedDateTime.of( localDateTime, zoneId ).toInstant().toEpochMilli() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert dateTimeCtx.offset() != null;
|
||||||
|
|
||||||
|
final HqlParser.OffsetContext offsetCtx = dateTimeCtx.offset();
|
||||||
|
assert offsetCtx != null;
|
||||||
|
|
||||||
|
// handle the offset
|
||||||
|
final int hourCtx = Integer.parseInt( offsetCtx.hour().INTEGER_LITERAL().getText() );
|
||||||
|
final int hour = offsetCtx.MINUS() == null
|
||||||
|
? hourCtx
|
||||||
|
: 0 - hourCtx;
|
||||||
|
final ZoneOffset offset = ZoneOffset.ofHoursMinutes(
|
||||||
|
hour,
|
||||||
|
offsetCtx.minute() == null
|
||||||
|
? 0
|
||||||
|
: Integer.parseInt( offsetCtx.minute().INTEGER_LITERAL().getText() )
|
||||||
|
);
|
||||||
|
|
||||||
|
timestamp = new Timestamp( OffsetDateTime.of( localDateTime, offset ).toInstant().toEpochMilli() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
return new SqmLiteral( timestamp, basicType( Timestamp.class ), creationContext.getNodeBuilder() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private <J> BasicDomainType<J> basicType(Class<J> javaType) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return creationContext.getJpaMetamodel().getTypeConfiguration().standardBasicTypeForJavaType( javaType );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalDate localDate(HqlParser.DateContext ctx) {
|
||||||
|
return LocalDate.of(
|
||||||
|
Integer.parseInt( ctx.year().getText() ),
|
||||||
|
Integer.parseInt( ctx.month().getText() ),
|
||||||
|
Integer.parseInt( ctx.day().getText() )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalTime localTime(HqlParser.TimeContext ctx) {
|
||||||
|
if ( ctx.second() != null ) {
|
||||||
|
int index = ctx.second().getText().indexOf('.');
|
||||||
|
if ( index < 0 ) {
|
||||||
|
return LocalTime.of(
|
||||||
|
Integer.parseInt( ctx.hour().getText() ),
|
||||||
|
Integer.parseInt( ctx.minute().getText() ),
|
||||||
|
Integer.parseInt( ctx.second().getText() )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return LocalTime.of(
|
||||||
|
Integer.parseInt( ctx.hour().getText() ),
|
||||||
|
Integer.parseInt( ctx.minute().getText() ),
|
||||||
|
Integer.parseInt( ctx.second().getText().substring( 0, index ) ),
|
||||||
|
Integer.parseInt( ctx.second().getText().substring( index + 1 ) )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return LocalTime.of(
|
||||||
|
Integer.parseInt( ctx.hour().getText() ),
|
||||||
|
Integer.parseInt( ctx.minute().getText() )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmLiteral interpretDateLiteral(HqlParser.DateLiteralContext dateLiteral) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return new SqmLiteral(
|
||||||
|
localDate( dateLiteral.date() ),
|
||||||
|
basicType( LocalDate.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmLiteral interpretJdbcDateLiteral(HqlParser.JdbcDateLiteralContext dateLiteral) {
|
||||||
|
if ( dateLiteral.genericTemporalLiteralText() != null ) {
|
||||||
|
final LocalDate parsed = DateTimeUtils.DATE.parse(
|
||||||
|
dateLiteral.genericTemporalLiteralText().STRING_LITERAL().getText(),
|
||||||
|
LocalDate::from
|
||||||
|
);
|
||||||
|
|
||||||
|
//noinspection unchecked,deprecation
|
||||||
|
return new SqmLiteral(
|
||||||
|
new Date( parsed.getYear(), parsed.getMonthValue(), parsed.getDayOfMonth() ),
|
||||||
|
basicType( Date.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final HqlParser.DateContext dateCtx = dateLiteral.date();
|
||||||
|
|
||||||
|
//noinspection unchecked,deprecation
|
||||||
|
return new SqmLiteral(
|
||||||
|
new Date(
|
||||||
|
Integer.parseInt( dateCtx.year().INTEGER_LITERAL().getText() ),
|
||||||
|
Integer.parseInt( dateCtx.month().INTEGER_LITERAL().getText() ),
|
||||||
|
Integer.parseInt( dateCtx.day().INTEGER_LITERAL().getText() )
|
||||||
|
),
|
||||||
|
basicType( Date.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmLiteral interpretTimeLiteral(HqlParser.TimeLiteralContext timeLiteral) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return new SqmLiteral(
|
||||||
|
localTime( timeLiteral.time() ),
|
||||||
|
basicType( LocalTime.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmLiteral interpretJdbcTimeLiteral(HqlParser.JdbcTimeLiteralContext timeLiteral) {
|
||||||
|
if ( timeLiteral.genericTemporalLiteralText() != null ) {
|
||||||
|
final LocalTime parsed = DateTimeUtils.TIME.parse(
|
||||||
|
timeLiteral.genericTemporalLiteralText().STRING_LITERAL().getText(),
|
||||||
|
LocalTime::from
|
||||||
|
);
|
||||||
|
|
||||||
|
//noinspection unchecked,deprecation
|
||||||
|
return new SqmLiteral(
|
||||||
|
new Time( parsed.getHour(), parsed.getMinute(), parsed.getSecond() ),
|
||||||
|
basicType( Time.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int seconds;
|
||||||
|
|
||||||
|
if ( timeLiteral.time().second().FLOAT_LITERAL() == null ) {
|
||||||
|
seconds = Integer.parseInt( timeLiteral.time().second().INTEGER_LITERAL().getText() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final float floatValue = Float.parseFloat( timeLiteral.time().second().FLOAT_LITERAL().getText() );
|
||||||
|
log.debugf( "Float-value encountered for seconds part of JDBC Date literal - ignoring fractional : " + floatValue );
|
||||||
|
seconds = (int) floatValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection unchecked,deprecation
|
||||||
|
return new SqmLiteral(
|
||||||
|
new Time(
|
||||||
|
Integer.parseInt( timeLiteral.time().hour().INTEGER_LITERAL().getText() ),
|
||||||
|
Integer.parseInt( timeLiteral.time().minute().INTEGER_LITERAL().getText() ),
|
||||||
|
seconds
|
||||||
|
),
|
||||||
|
basicType( Time.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmLiteral visitGeneralizedLiteral(HqlParser.GeneralizedLiteralContext ctx) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
private SqmLiteral<Boolean> booleanLiteral(boolean value) {
|
private SqmLiteral<Boolean> booleanLiteral(boolean value) {
|
||||||
final SqmExpressable expressionType = resolveExpressableTypeBasic( Boolean.class );
|
final SqmExpressable expressionType = resolveExpressableTypeBasic( Boolean.class );
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return new SqmLiteral<>( value, expressionType, creationContext.getQueryEngine().getCriteriaBuilder() );
|
return new SqmLiteral<>( value, expressionType, creationContext.getQueryEngine().getCriteriaBuilder() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private SqmLiteral<Character> characterLiteral(String text) {
|
|
||||||
if ( text.length() > 1 ) {
|
|
||||||
// todo : or just treat it as a String literal?
|
|
||||||
throw new ParsingException( "Value for CHARACTER_LITERAL token was more than 1 character" );
|
|
||||||
}
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
text.charAt( 0 ),
|
|
||||||
resolveExpressableTypeBasic( Character.class ),
|
|
||||||
creationContext.getNodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SqmLiteral<String> stringLiteral(String text) {
|
private SqmLiteral<String> stringLiteral(String text) {
|
||||||
return new SqmLiteral<>(
|
return new SqmLiteral<>(
|
||||||
text,
|
text,
|
||||||
|
@ -2208,7 +2547,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitDayField(HqlParser.DayFieldContext ctx) {
|
public Object visitDayField(HqlParser.DayFieldContext ctx) {
|
||||||
NodeBuilder nodeBuilder = creationContext.getNodeBuilder();
|
final NodeBuilder nodeBuilder = creationContext.getNodeBuilder();
|
||||||
if ( ctx.WEEK() != null ) {
|
if ( ctx.WEEK() != null ) {
|
||||||
return new SqmExtractUnit<>( DAY_OF_WEEK, resolveExpressableTypeBasic( Integer.class ), nodeBuilder );
|
return new SqmExtractUnit<>( DAY_OF_WEEK, resolveExpressableTypeBasic( Integer.class ), nodeBuilder );
|
||||||
}
|
}
|
||||||
|
@ -2223,7 +2562,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitWeekField(HqlParser.WeekFieldContext ctx) {
|
public Object visitWeekField(HqlParser.WeekFieldContext ctx) {
|
||||||
NodeBuilder nodeBuilder = creationContext.getNodeBuilder();
|
final NodeBuilder nodeBuilder = creationContext.getNodeBuilder();
|
||||||
if ( ctx.MONTH() != null ) {
|
if ( ctx.MONTH() != null ) {
|
||||||
//this is computed from DAY_OF_MONTH/7
|
//this is computed from DAY_OF_MONTH/7
|
||||||
return new SqmExtractUnit<>( WEEK_OF_MONTH, resolveExpressableTypeBasic( Integer.class ), nodeBuilder );
|
return new SqmExtractUnit<>( WEEK_OF_MONTH, resolveExpressableTypeBasic( Integer.class ), nodeBuilder );
|
||||||
|
@ -2270,27 +2609,245 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
private boolean isExtractingJdbcTemporalType;
|
private boolean isExtractingJdbcTemporalType;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitExtractFunction(HqlParser.ExtractFunctionContext ctx) {
|
public Object visitExtractFunction(HqlParser.ExtractFunctionContext extractFunctionCtx) {
|
||||||
final SqmExpression<?> expressionToExtract = (SqmExpression) ctx.expression().accept( this );
|
final SqmExpression<?> sqmTemporalExpr = (SqmExpression) extractFunctionCtx.expression().accept( this );
|
||||||
final SqmExtractUnit<?> extractFieldExpression;
|
final SqmExtractUnit<?> sqmExtractUnit;
|
||||||
|
|
||||||
if ( ctx.extractField() != null ) {
|
// Allow `#visitDateOrTimeField()` to know if we're extracting from a JDBC Timestamp or from a
|
||||||
extractFieldExpression = (SqmExtractUnit) ctx.extractField().accept( this);
|
// java.time LocalDateTime/OffsetDateTime
|
||||||
|
isExtractingJdbcTemporalType = isJdbcTemporalType( sqmTemporalExpr.getNodeType() );
|
||||||
|
|
||||||
|
if ( extractFunctionCtx.extractField() != null ) {
|
||||||
|
// for the case of the full ANSI syntax "extract(field from arg)"
|
||||||
|
sqmExtractUnit = (SqmExtractUnit) extractFunctionCtx.extractField().accept( this);
|
||||||
}
|
}
|
||||||
else if ( ctx.datetimeField() != null ) {
|
else if ( extractFunctionCtx.datetimeField() != null ) {
|
||||||
isExtractingJdbcTemporalType = isJdbcTemporalType( expressionToExtract.getNodeType() );
|
// for the shorter legacy Hibernate syntax "field(arg)"
|
||||||
extractFieldExpression = (SqmExtractUnit) ctx.datetimeField().accept( this );
|
sqmExtractUnit = (SqmExtractUnit) extractFunctionCtx.datetimeField().accept( this );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return expressionToExtract;
|
return sqmTemporalExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final TemporalUnit unit = sqmExtractUnit.getTemporalUnit();
|
||||||
|
switch ( unit ) {
|
||||||
|
case NANOSECOND: {
|
||||||
|
return extractNanoseconds( sqmTemporalExpr );
|
||||||
|
}
|
||||||
|
case OFFSET: {
|
||||||
|
// use formatdatetime(arg, 'xxx') to get the offset
|
||||||
|
return extractOffsetUsingFormat( sqmTemporalExpr );
|
||||||
|
}
|
||||||
|
case DATE:
|
||||||
|
case TIME: {
|
||||||
|
// use cast(arg as Type) to get the date or time part
|
||||||
|
// which might be javax.sql.Date / javax.sql.Time or
|
||||||
|
// java.time.LocalDate / java.time.LocalTime depending
|
||||||
|
// on the type of the expression we're extracting from
|
||||||
|
return extractDateOrTimeUsingCast(
|
||||||
|
sqmTemporalExpr,
|
||||||
|
sqmExtractUnit.getType()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case WEEK_OF_MONTH: {
|
||||||
|
// use ceiling(extract(day of month, arg)/7.0)
|
||||||
|
return extractWeek( sqmTemporalExpr, DAY_OF_MONTH );
|
||||||
|
}
|
||||||
|
case WEEK_OF_YEAR: {
|
||||||
|
// use ceiling(extract(day of year, arg)/7.0)
|
||||||
|
return extractWeek( sqmTemporalExpr, DAY_OF_YEAR );
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// otherwise it's something we expect the SQL dialect
|
||||||
|
// itself to understand, either natively, or via the
|
||||||
|
// registered function template for extract()
|
||||||
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return new SqmFunction(
|
return new SqmFunction(
|
||||||
"extract",
|
"extract",
|
||||||
getFunctionDescriptor( "extract" ),
|
getFunctionDescriptor( "extract" ),
|
||||||
extractFieldExpression.getNodeType(),
|
sqmExtractUnit.getNodeType(),
|
||||||
asList( extractFieldExpression, expressionToExtract ),
|
asList( sqmExtractUnit, sqmTemporalExpr ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmExpression<Long> extractNanoseconds(SqmExpression<?> sqmTemporalExpr) {
|
||||||
|
final SqmFunctionDescriptor roundFunctionDescriptor = getFunctionDescriptor( "round" );
|
||||||
|
final SqmFunctionDescriptor extractFunctionDescriptor = getFunctionDescriptor( "extract" );
|
||||||
|
|
||||||
|
final SqmLiteral<Float> nanoMultiplierLiteral = floatLiteral( "1e9" );
|
||||||
|
final SqmLiteral<Integer> zeroLiteral = integerLiteral( "0" );
|
||||||
|
|
||||||
|
final SqmSelfRenderingExpression<Long> sqmExtractSeconds = new SqmSelfRenderingExpression<>(
|
||||||
|
semanticQueryWalker -> extractFunctionDescriptor.generateSqlExpression(
|
||||||
|
"extract",
|
||||||
|
asList(
|
||||||
|
new SqmExtractUnit<>(
|
||||||
|
SECOND,
|
||||||
|
StandardBasicTypes.INTEGER,
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
),
|
||||||
|
sqmTemporalExpr
|
||||||
|
),
|
||||||
|
() -> (MappingModelExpressable) basicType( Long.class ),
|
||||||
|
(SqmToSqlAstConverter) semanticQueryWalker,
|
||||||
|
(SqlAstCreationState) semanticQueryWalker
|
||||||
|
),
|
||||||
|
basicType( Long.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
|
||||||
|
return new SqmSelfRenderingExpression<>(
|
||||||
|
semanticQueryWalker -> roundFunctionDescriptor.generateSqlExpression(
|
||||||
|
"round",
|
||||||
|
asList(
|
||||||
|
new SqmBinaryArithmetic<>(
|
||||||
|
BinaryArithmeticOperator.MULTIPLY,
|
||||||
|
sqmExtractSeconds,
|
||||||
|
nanoMultiplierLiteral,
|
||||||
|
basicType( Float.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
),
|
||||||
|
zeroLiteral
|
||||||
|
),
|
||||||
|
() -> (MappingModelExpressable) basicType( Float.class ),
|
||||||
|
(SqmToSqlAstConverter) semanticQueryWalker,
|
||||||
|
(SqlAstCreationState) semanticQueryWalker
|
||||||
|
),
|
||||||
|
basicType( Long.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmExpression<?> extractDateOrTimeUsingCast(
|
||||||
|
SqmExpression<?> expressionToExtract,
|
||||||
|
AllowableFunctionReturnType<?> type) {
|
||||||
|
return new SqmFunction<>(
|
||||||
|
"cast",
|
||||||
|
getFunctionDescriptor( "cast" ),
|
||||||
|
type,
|
||||||
|
asList(
|
||||||
|
expressionToExtract,
|
||||||
|
new SqmCastTarget<>(
|
||||||
|
type,
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmExpression<ZoneOffset> extractOffsetUsingFormat(SqmExpression<?> expressionToExtract) {
|
||||||
|
return new SqmFunction<>(
|
||||||
|
"formatdatetime",
|
||||||
|
getFunctionDescriptor( "formatdatetime" ),
|
||||||
|
basicType( ZoneOffset.class ),
|
||||||
|
asList(
|
||||||
|
expressionToExtract,
|
||||||
|
new SqmFormat(
|
||||||
|
"xxx", //pattern for timezone offset
|
||||||
|
basicType( String.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmExpression<Integer> extractWeek(
|
||||||
|
SqmExpression<?> expressionToExtract,
|
||||||
|
TemporalUnit dayOf) {
|
||||||
|
final BasicDomainType<Integer> intType = basicType( Integer.class );
|
||||||
|
|
||||||
|
final SqmFunctionDescriptor extractFunctionDescriptor = getFunctionDescriptor( "extract" );
|
||||||
|
|
||||||
|
final SqmFunction<Integer> extractDayOf = new SqmFunction<>(
|
||||||
|
"extract",
|
||||||
|
extractFunctionDescriptor,
|
||||||
|
intType,
|
||||||
|
asList(
|
||||||
|
new SqmExtractUnit<>(
|
||||||
|
dayOf,
|
||||||
|
intType,
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
),
|
||||||
|
expressionToExtract
|
||||||
|
),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
|
||||||
|
final SqmFunction<Integer> extractDayOfWeek = new SqmFunction<>(
|
||||||
|
"extract",
|
||||||
|
extractFunctionDescriptor,
|
||||||
|
intType,
|
||||||
|
asList(
|
||||||
|
new SqmExtractUnit<>(
|
||||||
|
DAY_OF_WEEK,
|
||||||
|
intType,
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
),
|
||||||
|
expressionToExtract
|
||||||
|
),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
|
||||||
|
final SqmBinaryArithmetic<Integer> subtraction = new SqmBinaryArithmetic<>(
|
||||||
|
BinaryArithmeticOperator.SUBTRACT,
|
||||||
|
extractDayOf,
|
||||||
|
extractDayOfWeek,
|
||||||
|
intType,
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
|
||||||
|
final SqmBinaryArithmetic<Float> division = new SqmBinaryArithmetic<>(
|
||||||
|
BinaryArithmeticOperator.DIVIDE,
|
||||||
|
subtraction,
|
||||||
|
floatLiteral( "7.0" ),
|
||||||
|
basicType( Float.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
|
||||||
|
return new SqmBinaryArithmetic<>(
|
||||||
|
BinaryArithmeticOperator.ADD,
|
||||||
|
new SqmFunction<>(
|
||||||
|
"ceiling",
|
||||||
|
getFunctionDescriptor( "ceiling" ),
|
||||||
|
intType,
|
||||||
|
Collections.singletonList( division ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
),
|
||||||
|
integerLiteral("1"),
|
||||||
|
intType,
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmFunction visitFormatFunction(HqlParser.FormatFunctionContext ctx) {
|
||||||
|
final SqmExpression<?> expressionToCast = (SqmExpression) ctx.expression().accept( this );
|
||||||
|
final SqmFormat format = visitFormat( ctx.format() );
|
||||||
|
|
||||||
|
return new SqmFunction<>(
|
||||||
|
"formatdatetime",
|
||||||
|
getFunctionDescriptor( "formatdatetime" ),
|
||||||
|
basicType( String.class ),
|
||||||
|
asList( expressionToCast, format ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmFormat visitFormat(HqlParser.FormatContext ctx) {
|
||||||
|
final String formatPattern = ctx.STRING_LITERAL().getText();
|
||||||
|
// if (!FORMAT.matcher(format).matches()) {
|
||||||
|
// throw new SemanticException("illegal format pattern: '" + format + "'");
|
||||||
|
// }
|
||||||
|
return new SqmFormat(
|
||||||
|
formatPattern,
|
||||||
|
basicType( String.class ),
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2633,20 +3190,6 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmLiteral<Character> visitTrimCharacter(HqlParser.TrimCharacterContext ctx) {
|
public SqmLiteral<Character> visitTrimCharacter(HqlParser.TrimCharacterContext ctx) {
|
||||||
// todo (6.0) : we should delay this until we are walking the SQM
|
|
||||||
|
|
||||||
if ( ctx.CHARACTER_LITERAL() != null ) {
|
|
||||||
final String trimCharText = ctx.CHARACTER_LITERAL().getText();
|
|
||||||
if ( trimCharText.length() != 1 ) {
|
|
||||||
throw new SemanticException( "Expecting [trim character] for TRIM function to be single character, found : " + trimCharText );
|
|
||||||
}
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
trimCharText.charAt( 0 ),
|
|
||||||
resolveExpressableTypeBasic( Character.class ),
|
|
||||||
creationContext.getNodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ctx.STRING_LITERAL() != null ) {
|
if ( ctx.STRING_LITERAL() != null ) {
|
||||||
final String trimCharText = ctx.STRING_LITERAL().getText();
|
final String trimCharText = ctx.STRING_LITERAL().getText();
|
||||||
if ( trimCharText.length() != 1 ) {
|
if ( trimCharText.length() != 1 ) {
|
||||||
|
@ -2971,6 +3514,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
SqmPath result = attribute.getElementPathSource().createSqmPath(
|
SqmPath result = attribute.getElementPathSource().createSqmPath(
|
||||||
pluralAttributePath,
|
pluralAttributePath,
|
||||||
this
|
this
|
||||||
|
|
|
@ -69,9 +69,11 @@ import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
||||||
|
@ -125,6 +127,7 @@ import org.hibernate.sql.ast.tree.expression.CastTarget;
|
||||||
import org.hibernate.sql.ast.tree.expression.Distinct;
|
import org.hibernate.sql.ast.tree.expression.Distinct;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
import org.hibernate.sql.ast.tree.expression.ExtractUnit;
|
import org.hibernate.sql.ast.tree.expression.ExtractUnit;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Format;
|
||||||
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.Star;
|
import org.hibernate.sql.ast.tree.expression.Star;
|
||||||
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
||||||
|
@ -781,6 +784,10 @@ public abstract class BaseSqmToSqlAstConverter
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Expression visitLiteral(SqmLiteral literal) {
|
public Expression visitLiteral(SqmLiteral literal) {
|
||||||
|
if ( literal instanceof SqmLiteralNull ) {
|
||||||
|
return new QueryLiteral( null, (BasicValuedMapping) inferableTypeAccessStack.getCurrent().get() );
|
||||||
|
}
|
||||||
|
|
||||||
return new QueryLiteral(
|
return new QueryLiteral(
|
||||||
literal.getLiteralValue(),
|
literal.getLiteralValue(),
|
||||||
(BasicValuedMapping) SqmMappingModelHelper.resolveMappingModelExpressable(
|
(BasicValuedMapping) SqmMappingModelHelper.resolveMappingModelExpressable(
|
||||||
|
@ -939,13 +946,11 @@ public abstract class BaseSqmToSqlAstConverter
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Expression visitFunction(SqmFunction sqmFunction) {
|
public Expression visitFunction(SqmFunction sqmFunction) {
|
||||||
final SqmFunctionDescriptor functionDescriptor = creationContext.getSessionFactory()
|
final SqmFunctionDescriptor functionDescriptor = sqmFunction.getFunctionDescriptor();
|
||||||
.getQueryEngine()
|
|
||||||
.getSqmFunctionRegistry()
|
|
||||||
.getFunctionDescriptor( sqmFunction.getFunctionName() );
|
|
||||||
|
|
||||||
shallownessStack.push( Shallowness.FUNCTION );
|
shallownessStack.push( Shallowness.FUNCTION );
|
||||||
try {
|
try {
|
||||||
|
//noinspection unchecked
|
||||||
return functionDescriptor.generateSqlExpression(
|
return functionDescriptor.generateSqlExpression(
|
||||||
sqmFunction.getFunctionName(),
|
sqmFunction.getFunctionName(),
|
||||||
sqmFunction.getArguments(),
|
sqmFunction.getArguments(),
|
||||||
|
@ -1009,6 +1014,14 @@ public abstract class BaseSqmToSqlAstConverter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitFormat(SqmFormat sqmFormat) {
|
||||||
|
return new Format(
|
||||||
|
sqmFormat.getLiteralValue(),
|
||||||
|
(BasicValuedMapping) sqmFormat.getNodeType()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
// public Object visitAbsFunction(SqmAbsFunction function) {
|
// public Object visitAbsFunction(SqmAbsFunction function) {
|
||||||
// shallownessStack.push( Shallowness.FUNCTION );
|
// shallownessStack.push( Shallowness.FUNCTION );
|
||||||
|
@ -1425,7 +1438,7 @@ public abstract class BaseSqmToSqlAstConverter
|
||||||
return new BinaryArithmeticExpression(
|
return new BinaryArithmeticExpression(
|
||||||
(Expression) expression.getLeftHandOperand().accept( this ), interpret( expression.getOperator() ),
|
(Expression) expression.getLeftHandOperand().accept( this ), interpret( expression.getOperator() ),
|
||||||
(Expression) expression.getRightHandOperand().accept( this ),
|
(Expression) expression.getRightHandOperand().accept( this ),
|
||||||
determineValueMapping( expression )
|
(BasicValuedMapping) determineValueMapping( expression )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
|
|
@ -13,13 +13,13 @@ import java.util.function.Consumer;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||||
|
import org.hibernate.sql.ast.SqlAstWalker;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
|
||||||
import org.hibernate.sql.ast.SqlAstWalker;
|
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression;
|
import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression;
|
||||||
|
@ -100,13 +100,11 @@ public class BasicValuedPathInterpretation<T> implements AssignableSqmPathInterp
|
||||||
|
|
||||||
assert tableGroup != null;
|
assert tableGroup != null;
|
||||||
this.tableGroup = tableGroup;
|
this.tableGroup = tableGroup;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPath<T> getInterpretedSqmPath() {
|
public NavigablePath getNavigablePath() {
|
||||||
return sqmPath;
|
return sqmPath.getNavigablePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.function.Consumer;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
||||||
|
@ -78,8 +79,8 @@ public class EmbeddableValuedPathInterpretation<T> implements AssignableSqmPathI
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPath<T> getInterpretedSqmPath() {
|
public NavigablePath getNavigablePath() {
|
||||||
return sqmPath;
|
return sqmPath.getNavigablePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.query.sqm.sql.internal;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||||
|
@ -62,13 +63,13 @@ public class EntityValuedPathInterpretation<T> implements SqmPathInterpretation<
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPath<T> getInterpretedSqmPath() {
|
public NavigablePath getNavigablePath() {
|
||||||
return sqmPath;
|
return sqmPath.getNavigablePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModelPart getExpressionType() {
|
public ModelPart getExpressionType() {
|
||||||
return null;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,16 +16,11 @@ import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
* for path interpretations because it can (and likely) contains multiple SqlExpressions (entity to its columns, e.g.)
|
* for path interpretations because it can (and likely) contains multiple SqlExpressions (entity to its columns, e.g.)
|
||||||
*
|
*
|
||||||
* @see org.hibernate.query.sqm.sql.SqmToSqlAstConverter
|
* @see org.hibernate.query.sqm.sql.SqmToSqlAstConverter
|
||||||
* @see #getInterpretedSqmPath
|
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SqmPathInterpretation<T> extends Expression, DomainResultProducer<T> {
|
public interface SqmPathInterpretation<T> extends Expression, DomainResultProducer<T> {
|
||||||
default NavigablePath getNavigablePath() {
|
NavigablePath getNavigablePath();
|
||||||
return getInterpretedSqmPath().getNavigablePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
SqmPath<T> getInterpretedSqmPath();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
ModelPart getExpressionType();
|
ModelPart getExpressionType();
|
||||||
|
|
|
@ -55,6 +55,10 @@ public class SqmFunction<T> extends AbstractSqmExpression<T> implements JpaFunct
|
||||||
this.arguments = arguments;
|
this.arguments = arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SqmFunctionDescriptor getFunctionDescriptor() {
|
||||||
|
return functionDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFunctionName() {
|
public String getFunctionName() {
|
||||||
return functionName;
|
return functionName;
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.query.sqm.tree.expression;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
|
import org.hibernate.query.sqm.SqmExpressable;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SqmSelfRenderingExpression<T> extends AbstractSqmExpression<T> implements SqmExpression<T> {
|
||||||
|
private final Function<SemanticQueryWalker, Expression> renderer;
|
||||||
|
|
||||||
|
public SqmSelfRenderingExpression(
|
||||||
|
Function<SemanticQueryWalker, Expression> renderer,
|
||||||
|
SqmExpressable<T> type,
|
||||||
|
NodeBuilder criteriaBuilder) {
|
||||||
|
super( type, criteriaBuilder );
|
||||||
|
this.renderer = renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (X) renderer.apply( walker );
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,8 @@ public class SqmSelection<T> extends AbstractSqmNode implements SqmAliasedNode<T
|
||||||
SqmSelectableNode<T> selectableNode,
|
SqmSelectableNode<T> selectableNode,
|
||||||
NodeBuilder nodeBuilder) {
|
NodeBuilder nodeBuilder) {
|
||||||
super( nodeBuilder );
|
super( nodeBuilder );
|
||||||
|
|
||||||
|
assert selectableNode != null;
|
||||||
this.selectableNode = selectableNode;
|
this.selectableNode = selectableNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +33,8 @@ public class SqmSelection<T> extends AbstractSqmNode implements SqmAliasedNode<T
|
||||||
String alias,
|
String alias,
|
||||||
NodeBuilder nodeBuilder) {
|
NodeBuilder nodeBuilder) {
|
||||||
super( nodeBuilder );
|
super( nodeBuilder );
|
||||||
|
|
||||||
|
assert selectableNode != null;
|
||||||
this.selectableNode = selectableNode;
|
this.selectableNode = selectableNode;
|
||||||
selectableNode.alias( alias );
|
selectableNode.alias( alias );
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ import org.hibernate.sql.ast.tree.select.SortSpecification;
|
||||||
import org.hibernate.sql.exec.internal.JdbcParametersImpl;
|
import org.hibernate.sql.exec.internal.JdbcParametersImpl;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
||||||
|
import org.hibernate.type.descriptor.sql.JdbcLiteralFormatter;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
import static org.hibernate.sql.ast.spi.SqlAppender.CLOSE_PARENTHESIS;
|
import static org.hibernate.sql.ast.spi.SqlAppender.CLOSE_PARENTHESIS;
|
||||||
|
@ -803,9 +804,11 @@ public abstract class AbstractSqlAstWalker
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression) {
|
public void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression) {
|
||||||
|
appendSql( "(" );
|
||||||
arithmeticExpression.getLeftHandOperand().accept( this );
|
arithmeticExpression.getLeftHandOperand().accept( this );
|
||||||
appendSql( arithmeticExpression.getOperator().getOperatorSqlTextString() );
|
appendSql( arithmeticExpression.getOperator().getOperatorSqlTextString() );
|
||||||
arithmeticExpression.getRightHandOperand().accept( this );
|
arithmeticExpression.getRightHandOperand().accept( this );
|
||||||
|
appendSql( ")" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.sqm.mutation.internal.cte.CteStrategy;
|
import org.hibernate.query.sqm.mutation.internal.cte.CteStrategy;
|
||||||
|
@ -52,6 +53,11 @@ public class CteTableGroup implements TableGroup {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getExpressionType() {
|
||||||
|
return getModelPart();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<TableGroupJoin> getTableGroupJoins() {
|
public Set<TableGroupJoin> getTableGroupJoins() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
|
|
|
@ -6,10 +6,17 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.sql.ast.tree.expression;
|
package org.hibernate.sql.ast.tree.expression;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||||
import org.hibernate.query.BinaryArithmeticOperator;
|
import org.hibernate.query.BinaryArithmeticOperator;
|
||||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||||
import org.hibernate.sql.ast.SqlAstWalker;
|
import org.hibernate.sql.ast.SqlAstWalker;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||||
|
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -20,13 +27,13 @@ public class BinaryArithmeticExpression implements Expression, DomainResultProdu
|
||||||
private final BinaryArithmeticOperator operator;
|
private final BinaryArithmeticOperator operator;
|
||||||
private final Expression rhsOperand;
|
private final Expression rhsOperand;
|
||||||
|
|
||||||
private final MappingModelExpressable resultType;
|
private final BasicValuedMapping resultType;
|
||||||
|
|
||||||
public BinaryArithmeticExpression(
|
public BinaryArithmeticExpression(
|
||||||
Expression lhsOperand,
|
Expression lhsOperand,
|
||||||
BinaryArithmeticOperator operator,
|
BinaryArithmeticOperator operator,
|
||||||
Expression rhsOperand,
|
Expression rhsOperand,
|
||||||
MappingModelExpressable resultType) {
|
BasicValuedMapping resultType) {
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
this.lhsOperand = lhsOperand;
|
this.lhsOperand = lhsOperand;
|
||||||
this.rhsOperand = rhsOperand;
|
this.rhsOperand = rhsOperand;
|
||||||
|
@ -34,7 +41,7 @@ public class BinaryArithmeticExpression implements Expression, DomainResultProdu
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MappingModelExpressable getExpressionType() {
|
public BasicValuedMapping getExpressionType() {
|
||||||
return resultType;
|
return resultType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,22 +50,37 @@ public class BinaryArithmeticExpression implements Expression, DomainResultProdu
|
||||||
walker.visitBinaryArithmeticExpression( this );
|
walker.visitBinaryArithmeticExpression( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
@Override
|
||||||
// public DomainResult createDomainResult(
|
public DomainResult createDomainResult(
|
||||||
// String resultVariable,
|
String resultVariable,
|
||||||
// DomainResultCreationState creationState) {
|
DomainResultCreationState creationState) {
|
||||||
// final SqlSelection sqlSelection = creationState.getSqlExpressionResolver().resolveSqlSelection(
|
final SqlSelection sqlSelection = creationState.getSqlAstCreationState().getSqlExpressionResolver().resolveSqlSelection(
|
||||||
// this,
|
this,
|
||||||
// getType().getJavaTypeDescriptor(),
|
resultType.getBasicType().getJavaTypeDescriptor(),
|
||||||
// creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration()
|
creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration()
|
||||||
// );
|
);
|
||||||
// //noinspection unchecked
|
|
||||||
// return new ScalarDomainResultImpl(
|
//noinspection unchecked
|
||||||
// sqlSelection.getValuesArrayPosition(),
|
return new BasicResult(
|
||||||
// resultVariable,
|
sqlSelection.getValuesArrayPosition(),
|
||||||
// resultType.getJavaTypeDescriptor()
|
resultVariable,
|
||||||
// );
|
resultType.getBasicType().getJavaTypeDescriptor()
|
||||||
// }
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlSelection createSqlSelection(
|
||||||
|
int jdbcPosition,
|
||||||
|
int valuesArrayPosition,
|
||||||
|
JavaTypeDescriptor javaTypeDescriptor,
|
||||||
|
TypeConfiguration typeConfiguration) {
|
||||||
|
return new SqlSelectionImpl(
|
||||||
|
jdbcPosition,
|
||||||
|
valuesArrayPosition,
|
||||||
|
this,
|
||||||
|
resultType.getJdbcMapping()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the left-hand operand.
|
* Get the left-hand operand.
|
||||||
|
|
|
@ -9,11 +9,11 @@ package org.hibernate.sql.ast.tree.from;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ import org.hibernate.sql.ast.spi.SqlAliasBase;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractTableGroup extends AbstractColumnReferenceQualifier implements TableGroup {
|
public abstract class AbstractTableGroup extends AbstractColumnReferenceQualifier implements TableGroup {
|
||||||
|
|
||||||
private final NavigablePath navigablePath;
|
private final NavigablePath navigablePath;
|
||||||
private final TableGroupProducer producer;
|
private final TableGroupProducer producer;
|
||||||
private final LockMode lockMode;
|
private final LockMode lockMode;
|
||||||
|
@ -78,6 +77,11 @@ public abstract class AbstractTableGroup extends AbstractColumnReferenceQualifie
|
||||||
return producer;
|
return producer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getExpressionType() {
|
||||||
|
return getModelPart();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LockMode getLockMode() {
|
public LockMode getLockMode() {
|
||||||
return lockMode;
|
return lockMode;
|
||||||
|
|
|
@ -15,6 +15,7 @@ import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
|
|
||||||
|
@ -43,6 +44,11 @@ public class CompositeTableGroup implements VirtualTableGroup {
|
||||||
return navigablePath;
|
return navigablePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddableValuedModelPart getExpressionType() {
|
||||||
|
return getModelPart();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getGroupAlias() {
|
public String getGroupAlias() {
|
||||||
// none, although we could also delegate to the underlyingTableGroup's group-alias
|
// none, although we could also delegate to the underlyingTableGroup's group-alias
|
||||||
|
@ -50,7 +56,7 @@ public class CompositeTableGroup implements VirtualTableGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModelPartContainer getModelPart() {
|
public EmbeddableValuedModelPart getModelPart() {
|
||||||
return compositionMapping;
|
return compositionMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
|
|
||||||
|
@ -41,6 +42,11 @@ public class MutatingTableReferenceGroupWrapper implements VirtualTableGroup {
|
||||||
return navigablePath;
|
return navigablePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getExpressionType() {
|
||||||
|
return getModelPart();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getGroupAlias() {
|
public String getGroupAlias() {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.LockMode;
|
||||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||||
|
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
|
||||||
import org.hibernate.sql.ast.SqlAstWalker;
|
import org.hibernate.sql.ast.SqlAstWalker;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
|
@ -26,7 +27,7 @@ import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface TableGroup extends SqlAstNode, ColumnReferenceQualifier, DomainResultProducer {
|
public interface TableGroup extends SqlAstNode, ColumnReferenceQualifier, SqmPathInterpretation, DomainResultProducer {
|
||||||
NavigablePath getNavigablePath();
|
NavigablePath getNavigablePath();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||||
import org.hibernate.persister.entity.UnionSubclassEntityPersister;
|
import org.hibernate.persister.entity.UnionSubclassEntityPersister;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
|
@ -40,6 +41,11 @@ public class UnionTableGroup implements VirtualTableGroup {
|
||||||
return navigablePath;
|
return navigablePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getExpressionType() {
|
||||||
|
return getModelPart();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getGroupAlias() {
|
public String getGroupAlias() {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.internal.EntityCollectionPart;
|
import org.hibernate.metamodel.mapping.internal.EntityCollectionPart;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.ast.SqlAstWalker;
|
import org.hibernate.sql.ast.SqlAstWalker;
|
||||||
|
@ -42,6 +43,11 @@ public class EntityCollectionPartTableGroup implements TableGroup {
|
||||||
return collectionPartPath;
|
return collectionPartPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getExpressionType() {
|
||||||
|
return getModelPart();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getGroupAlias() {
|
public String getGroupAlias() {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -7,10 +7,16 @@
|
||||||
package org.hibernate.type.descriptor;
|
package org.hibernate.type.descriptor;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.DateTimeFormatterBuilder;
|
import java.time.format.DateTimeFormatterBuilder;
|
||||||
import java.time.temporal.ChronoField;
|
import java.time.temporal.ChronoField;
|
||||||
import java.time.temporal.TemporalAccessor;
|
import java.time.temporal.TemporalAccessor;
|
||||||
|
import java.time.temporal.TemporalQueries;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
@ -61,6 +67,16 @@ public final class DateTimeUtils {
|
||||||
.optionalStart().appendZoneOrOffsetId().optionalEnd()
|
.optionalStart().appendZoneOrOffsetId().optionalEnd()
|
||||||
.toFormatter();
|
.toFormatter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pattern used for parsing literal dates in HQL.
|
||||||
|
*/
|
||||||
|
public static final DateTimeFormatter DATE = ISO_LOCAL_DATE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pattern used for parsing literal times in HQL.
|
||||||
|
*/
|
||||||
|
public static final DateTimeFormatter TIME = ISO_LOCAL_TIME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pattern used for parsing literal offset datetimes in HQL.
|
* Pattern used for parsing literal offset datetimes in HQL.
|
||||||
*
|
*
|
||||||
|
@ -170,4 +186,79 @@ public final class DateTimeUtils {
|
||||||
return formatter;
|
return formatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void main(String... args) {
|
||||||
|
final ZoneId localTzId = ZoneId.systemDefault();
|
||||||
|
System.out.printf( "Local tz : %s\n", localTzId );
|
||||||
|
|
||||||
|
final String[] values = new String[] {
|
||||||
|
"1999-12-31 12:59:59.3",
|
||||||
|
"1999-12-31 12:59:59 +02:00",
|
||||||
|
"1999-12-31 12:59:59 UTC",
|
||||||
|
"1999-12-31 12:59:59 UTC+02:00",
|
||||||
|
"1999-12-31 12:59:59 " + localTzId.getId()
|
||||||
|
};
|
||||||
|
|
||||||
|
for ( String value : values ) {
|
||||||
|
final TemporalAccessor parsed = DATE_TIME.parseBest(
|
||||||
|
value,
|
||||||
|
OffsetDateTime::from,
|
||||||
|
ZonedDateTime::from,
|
||||||
|
LocalDateTime::from
|
||||||
|
);
|
||||||
|
|
||||||
|
System.out.println( value + " -> " + parsed + " (" + parsed.getClass().getName() + ")" );
|
||||||
|
|
||||||
|
final ZonedDateTime zdt;
|
||||||
|
|
||||||
|
if ( parsed instanceof LocalDateTime ) {
|
||||||
|
// here, "localTzId" would come from the "jdbc timezone" setting?
|
||||||
|
zdt = ( (LocalDateTime) parsed ).atZone( localTzId );
|
||||||
|
System.out.println( " - LocalDateTime adjusted to ZonedDateTime : " + parsed );
|
||||||
|
}
|
||||||
|
else if ( parsed instanceof OffsetDateTime ) {
|
||||||
|
zdt = ( (OffsetDateTime) parsed ).toZonedDateTime();
|
||||||
|
System.out.println( " - OffsetDateTime adjusted to ZonedDateTime : " + parsed );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
zdt = (ZonedDateTime) parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println( " - ZoneId = " + zdt.getZone().getId() );
|
||||||
|
System.out.println( " - offset = " + zdt.getOffset() );
|
||||||
|
System.out.println( " - normalized = " + zdt.getZone().normalized() );
|
||||||
|
|
||||||
|
final ZonedDateTime adjusted = zdt.withZoneSameInstant( localTzId );
|
||||||
|
System.out.println( " - adjusted = " + adjusted.toLocalDateTime() + " (zone-id:" + adjusted.getZone() + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TemporalAccessor transform(String text) {
|
||||||
|
return DATE_TIME.parse(
|
||||||
|
text,
|
||||||
|
(temporal) -> {
|
||||||
|
// see if there is an offset or tz
|
||||||
|
final ZoneId zoneOrOffset = temporal.query( TemporalQueries.zone() );
|
||||||
|
if ( zoneOrOffset != null ) {
|
||||||
|
final ZonedDateTime zdt = ZonedDateTime.from( temporal );
|
||||||
|
// EDIT: call normalized() to convert a ZoneId
|
||||||
|
// with constant offset, e.g., UTC+02:00, to ZoneOffset
|
||||||
|
if ( zoneOrOffset.normalized() instanceof ZoneOffset ) {
|
||||||
|
return zdt.toOffsetDateTime();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return zdt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise it's a LocalDateTime
|
||||||
|
return LocalDateTime.from( temporal );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OffsetDateTime usingOffset(String text) {
|
||||||
|
// does not work
|
||||||
|
final TemporalAccessor parsed = DATE_TIME.parse( text );
|
||||||
|
return OffsetDateTime.from( parsed );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,10 @@ import java.sql.Types;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterNumericData;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#BIGINT BIGINT} handling.
|
* Descriptor for {@link Types#BIGINT BIGINT} handling.
|
||||||
|
@ -38,6 +41,17 @@ public class BigIntTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Long.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return new JdbcLiteralFormatterNumericData( javaTypeDescriptor, Long.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -15,7 +15,9 @@ import java.sql.Types;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#BIT BIT} handling.
|
* Descriptor for {@link Types#BIT BIT} handling.
|
||||||
|
@ -40,6 +42,11 @@ public class BitTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Boolean.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -16,7 +16,9 @@ import java.sql.Types;
|
||||||
import org.hibernate.engine.jdbc.BinaryStream;
|
import org.hibernate.engine.jdbc.BinaryStream;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#BLOB BLOB} handling.
|
* Descriptor for {@link Types#BLOB BLOB} handling.
|
||||||
|
@ -40,6 +42,11 @@ public abstract class BlobTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Blob.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -15,7 +15,10 @@ import java.sql.Types;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterBoolean;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link java.sql.Types#BOOLEAN BOOLEAN} handling.
|
* Descriptor for {@link java.sql.Types#BOOLEAN BOOLEAN} handling.
|
||||||
|
@ -37,6 +40,17 @@ public class BooleanTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Boolean.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return new JdbcLiteralFormatterBoolean( javaTypeDescriptor );
|
||||||
|
}
|
||||||
|
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -14,10 +14,15 @@ import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterTemporal;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#DATE DATE} handling.
|
* Descriptor for {@link Types#DATE DATE} handling.
|
||||||
|
@ -40,6 +45,17 @@ public class DateTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Date.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
|
return new JdbcLiteralFormatterTemporal( javaTypeDescriptor, TemporalType.DATE );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -16,7 +16,10 @@ import java.sql.Types;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterNumericData;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#DECIMAL DECIMAL} handling.
|
* Descriptor for {@link Types#DECIMAL DECIMAL} handling.
|
||||||
|
@ -39,6 +42,17 @@ public class DecimalTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( BigDecimal.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return new JdbcLiteralFormatterNumericData( javaTypeDescriptor, BigDecimal.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -15,7 +15,10 @@ import java.sql.Types;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterNumericData;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#DOUBLE DOUBLE} handling.
|
* Descriptor for {@link Types#DOUBLE DOUBLE} handling.
|
||||||
|
@ -38,6 +41,17 @@ public class DoubleTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Double.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return new JdbcLiteralFormatterNumericData( javaTypeDescriptor, Double.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -8,6 +8,9 @@ package org.hibernate.type.descriptor.sql;
|
||||||
|
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#FLOAT FLOAT} handling.
|
* Descriptor for {@link Types#FLOAT FLOAT} handling.
|
||||||
*
|
*
|
||||||
|
@ -19,6 +22,11 @@ public class FloatTypeDescriptor extends RealTypeDescriptor {
|
||||||
public FloatTypeDescriptor() {
|
public FloatTypeDescriptor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Double.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSqlType() {
|
public int getSqlType() {
|
||||||
return Types.FLOAT;
|
return Types.FLOAT;
|
||||||
|
|
|
@ -15,7 +15,10 @@ import java.sql.Types;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterNumericData;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#INTEGER INTEGER} handling.
|
* Descriptor for {@link Types#INTEGER INTEGER} handling.
|
||||||
|
@ -38,6 +41,17 @@ public class IntegerTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Integer.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
|
return new JdbcLiteralFormatterNumericData( javaTypeDescriptor, Integer.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.sql.ast.spi;
|
package org.hibernate.type.descriptor.sql;
|
||||||
|
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
@ -12,13 +12,15 @@ import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
|
||||||
import org.hibernate.sql.ast.spi.JdbcLiteralFormatter;
|
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterCharacterData;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
import static org.hibernate.sql.ast.spi.JdbcLiteralFormatter.NULL;
|
import static org.hibernate.type.descriptor.sql.JdbcLiteralFormatter.NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#NVARCHAR NVARCHAR} handling.
|
* Descriptor for {@link Types#NVARCHAR NVARCHAR} handling.
|
||||||
|
@ -41,9 +43,15 @@ public class NVarcharTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( String.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
return (value, dialect, session) -> value == null ? NULL : "'" + value.toString() + "'";
|
//noinspection unchecked
|
||||||
|
return new JdbcLiteralFormatterCharacterData( javaTypeDescriptor, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,7 +15,10 @@ import java.sql.Types;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterNumericData;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#REAL REAL} handling.
|
* Descriptor for {@link Types#REAL REAL} handling.
|
||||||
|
@ -38,6 +41,17 @@ public class RealTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Float.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
|
return new JdbcLiteralFormatterNumericData( javaTypeDescriptor, Float.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -15,7 +15,10 @@ import java.sql.Types;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterNumericData;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#SMALLINT SMALLINT} handling.
|
* Descriptor for {@link Types#SMALLINT SMALLINT} handling.
|
||||||
|
@ -38,6 +41,17 @@ public class SmallIntTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Short.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
|
return new JdbcLiteralFormatterNumericData( javaTypeDescriptor, Short.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.type.descriptor.sql;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.hibernate.sql.ast.spi.JdbcLiteralFormatter;
|
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
|
|
|
@ -14,10 +14,15 @@ import java.sql.Time;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterTemporal;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#TIME TIME} handling.
|
* Descriptor for {@link Types#TIME TIME} handling.
|
||||||
|
@ -40,6 +45,17 @@ public class TimeTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Time.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
|
return new JdbcLiteralFormatterTemporal( javaTypeDescriptor, TemporalType.TIME );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -14,10 +14,15 @@ import java.sql.Timestamp;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterTemporal;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#TIMESTAMP TIMESTAMP} handling.
|
* Descriptor for {@link Types#TIMESTAMP TIMESTAMP} handling.
|
||||||
|
@ -40,6 +45,17 @@ public class TimestampTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Timestamp.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
|
return new JdbcLiteralFormatterTemporal( javaTypeDescriptor, TemporalType.TIMESTAMP );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -15,7 +15,10 @@ import java.sql.Types;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterNumericData;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#TINYINT TINYINT} handling.
|
* Descriptor for {@link Types#TINYINT TINYINT} handling.
|
||||||
|
@ -41,6 +44,17 @@ public class TinyIntTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Short.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
|
return new JdbcLiteralFormatterNumericData( javaTypeDescriptor, Short.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
|
@ -15,7 +15,9 @@ import java.sql.Types;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#VARBINARY VARBINARY} handling.
|
* Descriptor for {@link Types#VARBINARY VARBINARY} handling.
|
||||||
|
@ -37,6 +39,11 @@ public class VarbinaryTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( byte[].class );
|
||||||
|
}
|
||||||
|
|
||||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
|
||||||
|
|
|
@ -12,13 +12,13 @@ import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
|
||||||
import org.hibernate.sql.ast.spi.JdbcLiteralFormatter;
|
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterCharacterData;
|
||||||
import static org.hibernate.sql.ast.spi.JdbcLiteralFormatter.NULL;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#VARCHAR VARCHAR} handling.
|
* Descriptor for {@link Types#VARCHAR VARCHAR} handling.
|
||||||
|
@ -41,9 +41,15 @@ public class VarcharTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||||
|
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( String.class );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||||
return (value, dialect, session) -> value == null ? NULL : "'" + value.toString() + "'";
|
//noinspection unchecked
|
||||||
|
return new JdbcLiteralFormatterCharacterData( javaTypeDescriptor );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.type.descriptor.sql.internal;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.spi.BasicJdbcLiteralFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JdbcLiteralFormatter implementation for handling boolean literals
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class JdbcLiteralFormatterBoolean extends BasicJdbcLiteralFormatter {
|
||||||
|
public JdbcLiteralFormatterBoolean(JavaTypeDescriptor javaTypeDescriptor) {
|
||||||
|
super( javaTypeDescriptor );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJdbcLiteral(Object value, Dialect dialect, SharedSessionContractImplementor session) {
|
||||||
|
return unwrap( value, Boolean.class, session ).toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.type.descriptor.sql.internal;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.spi.BasicJdbcLiteralFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JdbcLiteralFormatter implementation for handling character data
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class JdbcLiteralFormatterCharacterData extends BasicJdbcLiteralFormatter {
|
||||||
|
private final boolean isNationalized;
|
||||||
|
|
||||||
|
public JdbcLiteralFormatterCharacterData(JavaTypeDescriptor javaTypeDescriptor) {
|
||||||
|
this( javaTypeDescriptor, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public JdbcLiteralFormatterCharacterData(JavaTypeDescriptor javaTypeDescriptor, boolean isNationalized) {
|
||||||
|
super( javaTypeDescriptor );
|
||||||
|
this.isNationalized = isNationalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJdbcLiteral(Object value, Dialect dialect, SharedSessionContractImplementor session) {
|
||||||
|
final String literalValue = unwrap( value, String.class, session );
|
||||||
|
|
||||||
|
if ( isNationalized ) {
|
||||||
|
// is there a standardized form for n-string literals? This is the SQL Server syntax for sure
|
||||||
|
return String.format( Locale.ROOT, "n'%s'", literalValue );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return String.format( Locale.ROOT, "'%s'", literalValue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.type.descriptor.sql.internal;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.spi.BasicJdbcLiteralFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class JdbcLiteralFormatterNumericData extends BasicJdbcLiteralFormatter {
|
||||||
|
private final Class<? extends Number> unwrapJavaType;
|
||||||
|
|
||||||
|
public JdbcLiteralFormatterNumericData(
|
||||||
|
JavaTypeDescriptor javaTypeDescriptor,
|
||||||
|
Class<? extends Number> unwrapJavaType) {
|
||||||
|
super( javaTypeDescriptor );
|
||||||
|
this.unwrapJavaType = unwrapJavaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJdbcLiteral(Object value, Dialect dialect, SharedSessionContractImplementor session) {
|
||||||
|
return unwrap( value, unwrapJavaType, session ).toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.type.descriptor.sql.internal;
|
||||||
|
|
||||||
|
import java.time.temporal.TemporalAccessor;
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.spi.BasicJdbcLiteralFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class JdbcLiteralFormatterTemporal extends BasicJdbcLiteralFormatter {
|
||||||
|
private final TemporalType precision;
|
||||||
|
|
||||||
|
public JdbcLiteralFormatterTemporal(JavaTypeDescriptor javaTypeDescriptor, TemporalType precision) {
|
||||||
|
super( javaTypeDescriptor );
|
||||||
|
this.precision = precision;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJdbcLiteral(Object value, Dialect dialect, SharedSessionContractImplementor session) {
|
||||||
|
// for performance reasons, avoid conversions if we can
|
||||||
|
if ( value instanceof java.util.Date ) {
|
||||||
|
return dialect.formatDateTimeLiteral(
|
||||||
|
(java.util.Date) value,
|
||||||
|
precision
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ( value instanceof java.util.Calendar ) {
|
||||||
|
return dialect.formatDateTimeLiteral(
|
||||||
|
(java.util.Calendar) value,
|
||||||
|
precision
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ( value instanceof TemporalAccessor ) {
|
||||||
|
return dialect.formatDateTimeLiteral(
|
||||||
|
(TemporalAccessor) value,
|
||||||
|
precision
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( precision) {
|
||||||
|
case DATE: {
|
||||||
|
return dialect.formatDateTimeLiteral(
|
||||||
|
unwrap( value, java.sql.Date.class, session ),
|
||||||
|
precision
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case TIME: {
|
||||||
|
return dialect.formatDateTimeLiteral(
|
||||||
|
unwrap( value, java.sql.Time.class, session ),
|
||||||
|
precision
|
||||||
|
);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return dialect.formatDateTimeLiteral(
|
||||||
|
unwrap( value, java.util.Date.class, session ),
|
||||||
|
precision
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.type.descriptor.sql.spi;
|
||||||
|
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.JdbcLiteralFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract JdbcLiteralFormatter implementation managing the JavaTypeDescriptor
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public abstract class AbstractJdbcLiteralFormatter implements JdbcLiteralFormatter {
|
||||||
|
private final JavaTypeDescriptor javaTypeDescriptor;
|
||||||
|
|
||||||
|
public AbstractJdbcLiteralFormatter(JavaTypeDescriptor javaTypeDescriptor) {
|
||||||
|
this.javaTypeDescriptor = javaTypeDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||||
|
return javaTypeDescriptor;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.type.descriptor.sql.spi;
|
||||||
|
|
||||||
|
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for JdbcLiteralFormatter implementations with a basic implementation of an unwrap method
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public abstract class BasicJdbcLiteralFormatter extends AbstractJdbcLiteralFormatter {
|
||||||
|
public BasicJdbcLiteralFormatter(JavaTypeDescriptor<?> javaTypeDescriptor) {
|
||||||
|
super( javaTypeDescriptor );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected <X> X unwrap(Object value, Class<X> unwrapType, SharedSessionContractImplementor session) {
|
||||||
|
assert value != null;
|
||||||
|
|
||||||
|
// for performance reasons, avoid conversions if we can
|
||||||
|
if ( unwrapType.isInstance( value ) ) {
|
||||||
|
return (X) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (X) getJavaTypeDescriptor().unwrap( value, unwrapType, session );
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,35 +6,92 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.query.hql;
|
package org.hibernate.orm.test.query.hql;
|
||||||
|
|
||||||
import org.hibernate.boot.MetadataSources;
|
|
||||||
import org.hibernate.orm.test.query.sqm.BaseSqmUnitTest;
|
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
|
||||||
|
|
||||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class LiteralTests extends BaseSqmUnitTest {
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
@ServiceRegistry
|
||||||
|
@DomainModel( standardModels = StandardDomainModel.GAMBIT )
|
||||||
|
@SessionFactory
|
||||||
|
public class LiteralTests {
|
||||||
|
|
||||||
@Override
|
@Test
|
||||||
protected void applyMetadataSources(MetadataSources metadataSources) {
|
public void testJdbcTimeLiteral(SessionFactoryScope scope) {
|
||||||
StandardDomainModel.GAMBIT.getDescriptor().applyDomainModel( metadataSources );
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theTime = {t 12:30:00}" ).list();
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theTime = {t '12:30:00'}" ).list();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTimestampLiteral() {
|
public void testJdbcDateLiteral(SessionFactoryScope scope) {
|
||||||
final SqmSelectStatement sqm = interpretSelect( "from EntityOfBasics e1 where e1.theTimestamp = {ts '2018-01-01T12:30:00'}" );
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theDate = {d 1999-12-31}" ).list();
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theDate = {d '1999-12-31'}" ).list();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDateLiteral() {
|
public void testJdbcTimestampLiteral(SessionFactoryScope scope) {
|
||||||
final SqmSelectStatement sqm = interpretSelect( "from EntityOfBasics e1 where e1.theDate = {d '2018-01-01'}" );
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theDate = {ts 1999-12-31 12:30:00}" ).list();
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theDate = {ts '1999-12-31 12:30:00'}" ).list();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTimeLiteral() {
|
public void testLocalDateLiteral(SessionFactoryScope scope) {
|
||||||
final SqmSelectStatement sqm = interpretSelect( "from EntityOfBasics e1 where e1.theTime = {t '12:30:00'}" );
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theLocalDate = {1999-12-31}" ).list();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLocalTimeLiteral(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theLocalTime = {12:59:59}" ).list();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDateTimeLiteral(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
// todo (6.0) : removed this difference between the string-literal form and the date-time-field form (with/without 'T')
|
||||||
|
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theLocalDateTime = {1999-12-31 12:59:59}" ).list();
|
||||||
|
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theZonedDateTime = {1999-12-31 12:59:59 +01:00}" ).list();
|
||||||
|
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theZonedDateTime = {1999-12-31 12:59:59 CST}" ).list();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isolated(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theLocalDateTime = {1999-12-31 12:59:59}" ).list();
|
||||||
|
session.createQuery( "from EntityOfBasics e1 where e1.theZonedDateTime = {1999-12-31 12:59:59 +01:00}" ).list();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,6 @@ public class StandardFunctionTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@FailureExpected
|
|
||||||
public void testCoalesceFunction(SessionFactoryScope scope) {
|
public void testCoalesceFunction(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
|
@ -617,120 +616,176 @@ public class StandardFunctionTests {
|
||||||
public void isolated(SessionFactoryScope scope) {
|
public void isolated(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
session.createQuery("select extract(time from local_datetime), extract(date from local_datetime) from EntityOfBasics e")
|
session.createQuery("select extract(time from e.theTimestamp), extract(date from e.theTimestamp) from EntityOfBasics e").list();
|
||||||
.list();
|
session.createQuery("select extract(time from local_datetime), extract(date from local_datetime) from EntityOfBasics e").list();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@FailureExpected
|
// @FailureExpected
|
||||||
public void testExtractFunctionWithAssertions(SessionFactoryScope scope) {
|
public void testExtractFunctionWithAssertions(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
EntityOfBasics entity = new EntityOfBasics();
|
EntityOfBasics entity = new EntityOfBasics();
|
||||||
entity.setId(1);
|
entity.setId(1);
|
||||||
session.save(entity);
|
session.save(entity);
|
||||||
session.flush();
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(week of year from date '2019-01-01') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
|
"select extract(week of year from {2019-01-01}) from EntityOfBasics b where b.id = 1" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 1 )
|
is( 1 )
|
||||||
);
|
);
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(week of year from date '2019-01-05') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
|
"select extract(week of year from {2019-01-01}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 1 )
|
is( 1 )
|
||||||
);
|
);
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(week of year from date '2019-01-06') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
is(2)
|
"select extract(week of year from {2019-01-01}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
|
is( 1 )
|
||||||
|
);
|
||||||
|
assertThat(
|
||||||
|
session.createQuery(
|
||||||
|
"select extract(week of year from {2019-01-01}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
|
is( 1 )
|
||||||
);
|
);
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(week of month from date '2019-05-01') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
|
"select extract(week of year from {2019-01-05}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 1 )
|
is( 1 )
|
||||||
);
|
);
|
||||||
assertThat(
|
|
||||||
session.createQuery("select extract(week of month from date '2019-05-04') from EntityOfBasics").getResultList().get(0),
|
|
||||||
is(1)
|
|
||||||
);
|
|
||||||
assertThat(
|
|
||||||
session.createQuery("select extract(week of month from date '2019-05-05') from EntityOfBasics").getResultList().get(0),
|
|
||||||
is(2)
|
|
||||||
);
|
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(week from date '2019-05-27') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
|
"select extract(week of month from {2019-05-01}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
|
is( 1 )
|
||||||
|
);
|
||||||
|
|
||||||
|
assertThat(
|
||||||
|
session.createQuery( "select extract(week from {2019-05-27}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 22 )
|
is( 22 )
|
||||||
);
|
);
|
||||||
assertThat(
|
|
||||||
session.createQuery("select extract(week from date '2019-06-02') from EntityOfBasics").getResultList().get(0),
|
|
||||||
is(22)
|
|
||||||
);
|
|
||||||
assertThat(
|
|
||||||
session.createQuery("select extract(week from date '2019-06-03') from EntityOfBasics").getResultList().get(0),
|
|
||||||
is(23)
|
|
||||||
);
|
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(day of year from date '2019-05-30') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
|
"select extract(day of year from {2019-05-30}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 150 )
|
is( 150 )
|
||||||
);
|
);
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(day of month from date '2019-05-27') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
|
"select extract(day of month from {2019-05-27}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 27 )
|
is( 27 )
|
||||||
);
|
);
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(day from date '2019-05-31') from EntityOfBasics").getResultList().get(0),
|
session.createQuery( "select extract(day from {2019-05-31}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 31 )
|
is( 31 )
|
||||||
);
|
);
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(month from date '2019-05-31') from EntityOfBasics").getResultList().get(0),
|
session.createQuery( "select extract(month from {2019-05-31}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 5 )
|
is( 5 )
|
||||||
);
|
);
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(year from date '2019-05-31') from EntityOfBasics").getResultList().get(0),
|
session.createQuery( "select extract(year from {2019-05-31}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 2019 )
|
is( 2019 )
|
||||||
);
|
);
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(quarter from date '2019-05-31') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
|
"select extract(quarter from {2019-05-31}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 2 )
|
is( 2 )
|
||||||
);
|
);
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(day of week from date '2019-05-27') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
|
"select extract(day of week from {2019-05-27}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 2 )
|
is( 2 )
|
||||||
);
|
);
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(day of week from date '2019-05-31') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
|
"select extract(day of week from {2019-05-31}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 6 )
|
is( 6 )
|
||||||
);
|
);
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(second from time '14:12:10') from EntityOfBasics").getResultList().get(0),
|
session.createQuery( "select extract(second from {14:12:10}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 10f )
|
is( 10f )
|
||||||
);
|
);
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(minute from time '14:12:10') from EntityOfBasics").getResultList().get(0),
|
session.createQuery( "select extract(minute from {14:12:10}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 12 )
|
is( 12 )
|
||||||
);
|
);
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(hour from time '14:12:10') from EntityOfBasics").getResultList().get(0),
|
session.createQuery( "select extract(hour from {14:12:10}) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( 14 )
|
is( 14 )
|
||||||
);
|
);
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(date from current datetime) from EntityOfBasics").getResultList().get(0),
|
session.createQuery( "select extract(date from local_datetime) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
instanceOf( LocalDate.class )
|
instanceOf( LocalDate.class )
|
||||||
);
|
);
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select extract(time from current datetime) from EntityOfBasics").getResultList().get(0),
|
session.createQuery( "select extract(time from local_datetime) from EntityOfBasics" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
instanceOf( LocalTime.class )
|
instanceOf( LocalTime.class )
|
||||||
);
|
);
|
||||||
session.delete(entity);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "delete from EntityOfBasics" ).executeUpdate();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExtractFunctions(SessionFactoryScope scope) {
|
public void testExtractFunctions(SessionFactoryScope scope) {
|
||||||
|
@ -795,14 +850,8 @@ public class StandardFunctionTests {
|
||||||
public void testCountFunction(SessionFactoryScope scope) {
|
public void testCountFunction(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
session.createQuery("select count(*) from EntityOfBasics e")
|
session.createQuery("select count(e) from EntityOfBasics e").list();
|
||||||
.list();
|
session.createQuery("select count(distinct e) from EntityOfBasics e").list();
|
||||||
session.createQuery("select count(1) from EntityOfBasics e")
|
|
||||||
.list();
|
|
||||||
session.createQuery("select count(e) from EntityOfBasics e")
|
|
||||||
.list();
|
|
||||||
session.createQuery("select count(distinct e) from EntityOfBasics e")
|
|
||||||
.list();
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -820,7 +869,6 @@ public class StandardFunctionTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@FailureExpected
|
|
||||||
public void testFormat(SessionFactoryScope scope) {
|
public void testFormat(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
|
@ -830,24 +878,44 @@ public class StandardFunctionTests {
|
||||||
entity.setTheTime( new Time( 23, 10, 8 ) );
|
entity.setTheTime( new Time( 23, 10, 8 ) );
|
||||||
entity.setTheTimestamp( new Timestamp( System.currentTimeMillis() ) );
|
entity.setTheTimestamp( new Timestamp( System.currentTimeMillis() ) );
|
||||||
session.persist( entity );
|
session.persist( entity );
|
||||||
session.flush();
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
session.createQuery( "select format(e.theTime as 'hh:mm:ss aa') from EntityOfBasics e" )
|
session.createQuery( "select format(e.theTime as 'hh:mm:ss aa') from EntityOfBasics e" )
|
||||||
.list();
|
.list();
|
||||||
session.createQuery("select format(e.theDate as 'dd/MM/yy'), format(e.theDate as 'EEEE, MMMM dd, yyyy') from EntityOfBasics e")
|
session.createQuery(
|
||||||
|
"select format(e.theDate as 'dd/MM/yy'), format(e.theDate as 'EEEE, MMMM dd, yyyy') from EntityOfBasics e" )
|
||||||
.list();
|
.list();
|
||||||
session.createQuery("select format(e.theTimestamp as 'dd/MM/yyyy ''at'' HH:mm:ss') from EntityOfBasics e")
|
session.createQuery(
|
||||||
|
"select format(e.theTimestamp as 'dd/MM/yyyy ''at'' HH:mm:ss') from EntityOfBasics e" )
|
||||||
.list();
|
.list();
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select format(e.theDate as 'EEEE, dd/MM/yyyy') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
|
"select format(e.theDate as 'EEEE, dd/MM/yyyy') from EntityOfBasics e" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( "Monday, 25/03/1974" )
|
is( "Monday, 25/03/1974" )
|
||||||
);
|
);
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select format(e.theTime as '''Hello'', hh:mm:ss aa') from EntityOfBasics").getResultList().get(0),
|
session.createQuery(
|
||||||
|
"select format(e.theTime as '''Hello'', hh:mm:ss aa') from EntityOfBasics e" )
|
||||||
|
.getResultList()
|
||||||
|
.get( 0 ),
|
||||||
is( "Hello, 11:10:08 PM" )
|
is( "Hello, 11:10:08 PM" )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "delete EntityOfBasics" ).executeUpdate();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,11 @@ package org.hibernate.testing.orm.domain.gambit;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.sql.Clob;
|
import java.sql.Clob;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import javax.persistence.AttributeConverter;
|
import javax.persistence.AttributeConverter;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
|
@ -42,6 +47,11 @@ public class EntityOfBasics {
|
||||||
private Date theTime;
|
private Date theTime;
|
||||||
private Date theTimestamp;
|
private Date theTimestamp;
|
||||||
private Instant theInstant;
|
private Instant theInstant;
|
||||||
|
private LocalDateTime theLocalDateTime;
|
||||||
|
private LocalDate theLocalDate;
|
||||||
|
private LocalTime theLocalTime;
|
||||||
|
private OffsetDateTime theOffsetDateTime;
|
||||||
|
private ZonedDateTime theZonedDateTime;
|
||||||
private Gender gender;
|
private Gender gender;
|
||||||
private Gender convertedGender;
|
private Gender convertedGender;
|
||||||
private Gender ordinalGender;
|
private Gender ordinalGender;
|
||||||
|
@ -167,6 +177,46 @@ public class EntityOfBasics {
|
||||||
this.theInstant = theInstant;
|
this.theInstant = theInstant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getTheLocalDateTime() {
|
||||||
|
return theLocalDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTheLocalDateTime(LocalDateTime theLocalDateTime) {
|
||||||
|
this.theLocalDateTime = theLocalDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDate getTheLocalDate() {
|
||||||
|
return theLocalDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTheLocalDate(LocalDate theLocalDate) {
|
||||||
|
this.theLocalDate = theLocalDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalTime getTheLocalTime() {
|
||||||
|
return theLocalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTheLocalTime(LocalTime theLocalTime) {
|
||||||
|
this.theLocalTime = theLocalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getTheOffsetDateTime() {
|
||||||
|
return theOffsetDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTheOffsetDateTime(OffsetDateTime theOffsetDateTime) {
|
||||||
|
this.theOffsetDateTime = theOffsetDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZonedDateTime getTheZonedDateTime() {
|
||||||
|
return theZonedDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTheZonedDateTime(ZonedDateTime theZonedDateTime) {
|
||||||
|
this.theZonedDateTime = theZonedDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
public static class GenderConverter implements AttributeConverter<Gender,Character> {
|
public static class GenderConverter implements AttributeConverter<Gender,Character> {
|
||||||
@Override
|
@Override
|
||||||
public Character convertToDatabaseColumn(Gender attribute) {
|
public Character convertToDatabaseColumn(Gender attribute) {
|
||||||
|
|
Loading…
Reference in New Issue