Add support for FETCH clause, CTEs and set operations
This commit is contained in:
parent
f54072df4e
commit
4efffca23b
10
ci/build.sh
10
ci/build.sh
|
@ -4,15 +4,15 @@ goal=
|
|||
if [ "$RDBMS" == "derby" ]; then
|
||||
goal="-Pdb=derby"
|
||||
elif [ "$RDBMS" == "mariadb" ]; then
|
||||
goal="-Pdb=mariadb"
|
||||
goal="-Pdb=mariadb_ci"
|
||||
elif [ "$RDBMS" == "postgresql" ]; then
|
||||
goal="-Pdb=pgsql"
|
||||
goal="-Pdb=pgsql_ci"
|
||||
elif [ "$RDBMS" == "oracle" ]; then
|
||||
goal="-Pdb=oracle -Dhibernate.connection.url=jdbc:oracle:thin:@localhost:1521:XE -Dhibernate.connection.username=SYSTEM -Dhibernate.connection.password=Oracle18"
|
||||
goal="-Pdb=oracle_ci"
|
||||
elif [ "$RDBMS" == "db2" ]; then
|
||||
goal="-Pdb=db2 -Dhibernate.connection.url=jdbc:db2://localhost:50000/orm_test -Dhibernate.connection.username=orm_test -Dhibernate.connection.password=orm_test"
|
||||
goal="-Pdb=db2_ci"
|
||||
elif [ "$RDBMS" == "mssql" ]; then
|
||||
goal="-Pdb=mssql -Dhibernate.connection.url=jdbc:sqlserver://localhost:1433;databaseName= -Dhibernate.connection.username=sa -Dhibernate.connection.password=Hibernate_orm_test"
|
||||
goal="-Pdb=mssql_ci"
|
||||
fi
|
||||
|
||||
exec ./gradlew check ${goal} -Plog-test-progress=true --stacktrace
|
28
docker_db.sh
28
docker_db.sh
|
@ -12,7 +12,7 @@ mysql_8_0() {
|
|||
|
||||
mariadb() {
|
||||
docker rm -f mariadb || true
|
||||
docker run --name mariadb -e MYSQL_USER=hibernate_orm_test -e MYSQL_PASSWORD=hibernate_orm_test -e MYSQL_DATABASE=hibernate_orm_test -e MYSQL_ALLOW_EMPTY_PASSWORD=true -p3306:3306 -d mariadb:10.5.8 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||
docker run --name mariadb -e MYSQL_USER=hibernate_orm_test -e MYSQL_PASSWORD=hibernate_orm_test -e MYSQL_DATABASE=hibernate_orm_test -e MYSQL_ROOT_PASSWORD=hibernate_orm_test -p3306:3306 -d mariadb:10.5.8 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||
}
|
||||
|
||||
postgresql_9_5() {
|
||||
|
@ -20,12 +20,17 @@ postgresql_9_5() {
|
|||
docker run --name postgres -e POSTGRES_USER=hibernate_orm_test -e POSTGRES_PASSWORD=hibernate_orm_test -e POSTGRES_DB=hibernate_orm_test -p5432:5432 -d postgres:9.5
|
||||
}
|
||||
|
||||
postgresql_13() {
|
||||
docker rm -f postgres || true
|
||||
docker run --name postgres -e POSTGRES_USER=hibernate_orm_test -e POSTGRES_PASSWORD=hibernate_orm_test -e POSTGRES_DB=hibernate_orm_test -p5432:5432 -d postgres:13.0
|
||||
}
|
||||
|
||||
db2() {
|
||||
docker rm -f db2 || true
|
||||
docker run --name db2 --privileged -e DB2INSTANCE=orm_test -e DB2INST1_PASSWORD=orm_test -e DBNAME=orm_test -e LICENSE=accept -p 50000:50000 -d ibmcom/db2:11.5.0.0a
|
||||
docker run --name db2 --privileged -e DB2INSTANCE=orm_test -e DB2INST1_PASSWORD=orm_test -e DBNAME=orm_test -e LICENSE=accept -e AUTOCONFIG=false -e ARCHIVE_LOGS=false -e TO_CREATE_SAMPLEDB=false -e REPODB=false -p 50000:50000 -d ibmcom/db2:11.5.5.0
|
||||
# Give the container some time to start
|
||||
OUTPUT=
|
||||
while [[ $OUTPUT != *"Setup has completed"* ]]; do
|
||||
while [[ $OUTPUT != *"INSTANCE"* ]]; do
|
||||
echo "Waiting for DB2 to start..."
|
||||
sleep 10
|
||||
OUTPUT=$(docker logs db2)
|
||||
|
@ -36,6 +41,22 @@ db2() {
|
|||
mssql() {
|
||||
docker rm -f mssql || true
|
||||
docker run --name mssql -d -p 1433:1433 -e "SA_PASSWORD=Hibernate_orm_test" -e ACCEPT_EULA=Y microsoft/mssql-server-linux:2017-CU13
|
||||
sleep 5
|
||||
n=0
|
||||
until [ "$n" -ge 5 ]
|
||||
do
|
||||
# We need a database that uses a non-lock based MVCC approach
|
||||
# https://github.com/microsoft/homebrew-mssql-release/issues/2#issuecomment-682285561
|
||||
docker exec mssql bash -c 'echo "create database hibernate_orm_test collate SQL_Latin1_General_CP1_CI_AS; alter database hibernate_orm_test set READ_COMMITTED_SNAPSHOT ON" | /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Hibernate_orm_test -i /dev/stdin' && break
|
||||
echo "Waiting for SQL Server to start..."
|
||||
n=$((n+1))
|
||||
sleep 5
|
||||
done
|
||||
if [ "$n" -ge 5 ]; then
|
||||
echo "SQL Server failed to start and configure after 25 seconds"
|
||||
else
|
||||
echo "SQL Server successfully started"
|
||||
fi
|
||||
}
|
||||
|
||||
oracle() {
|
||||
|
@ -52,6 +73,7 @@ if [ -z ${1} ]; then
|
|||
echo -e "\tmysql_8_0"
|
||||
echo -e "\tmariadb"
|
||||
echo -e "\tpostgresql_9_5"
|
||||
echo -e "\tpostgresql_13"
|
||||
echo -e "\tdb2"
|
||||
echo -e "\tmssql"
|
||||
echo -e "\toracle"
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.apache.tools.ant.filters.ReplaceTokens
|
|||
// build a map of the database settings to use.
|
||||
ext {
|
||||
db = project.hasProperty('db') ? project.getProperty('db') : 'h2'
|
||||
def dbHost = System.getProperty( 'dbHost', 'localhost' )
|
||||
dbBundle = [
|
||||
h2 : [
|
||||
'db.dialect' : 'org.hibernate.dialect.H2Dialect',
|
||||
|
@ -26,47 +27,61 @@ ext {
|
|||
'jdbc.url' : 'jdbc:hsqldb:mem:test'
|
||||
],
|
||||
derby : [
|
||||
'db.dialect' : 'org.hibernate.dialect.DerbyTenSevenDialect',
|
||||
'db.dialect' : 'org.hibernate.dialect.DerbyDialect',
|
||||
'jdbc.driver': 'org.apache.derby.jdbc.EmbeddedDriver',
|
||||
'jdbc.user' : 'hibernate_orm_test',
|
||||
'jdbc.pass' : 'hibernate_orm_test',
|
||||
'jdbc.url' : 'jdbc:derby:target/tmp/derby/hibernate_orm_test;databaseName=hibernate_orm_test;create=true'
|
||||
],
|
||||
pgsql : [
|
||||
'db.dialect' : 'org.hibernate.dialect.PostgreSQL95Dialect',
|
||||
'db.dialect' : 'org.hibernate.dialect.PostgreSQLDialect',
|
||||
'jdbc.driver': 'org.postgresql.Driver',
|
||||
'jdbc.user' : 'hibernate_orm_test',
|
||||
'jdbc.pass' : 'hibernate_orm_test',
|
||||
'jdbc.url' : 'jdbc:postgresql:hibernate_orm_test'
|
||||
],
|
||||
pgsql_docker : [
|
||||
'db.dialect' : 'org.hibernate.dialect.PostgreSQL95Dialect',
|
||||
'db.dialect' : 'org.hibernate.dialect.PostgreSQLDialect',
|
||||
'jdbc.driver': 'org.postgresql.Driver',
|
||||
'jdbc.user' : 'hibernate_orm_test',
|
||||
'jdbc.pass' : 'hibernate_orm_test',
|
||||
'jdbc.url' : 'jdbc:postgresql://127.0.0.1/hibernate_orm_test'
|
||||
],
|
||||
pgsql_ci : [
|
||||
'db.dialect' : 'org.hibernate.dialect.PostgreSQLDialect',
|
||||
'jdbc.driver': 'org.postgresql.Driver',
|
||||
'jdbc.user' : 'hibernate_orm_test',
|
||||
'jdbc.pass' : 'hibernate_orm_test',
|
||||
'jdbc.url' : 'jdbc:postgresql://' + dbHost + '/hibernate_orm_test'
|
||||
],
|
||||
mysql : [
|
||||
'db.dialect' : 'org.hibernate.dialect.MySQL57Dialect',
|
||||
'db.dialect' : 'org.hibernate.dialect.MySQLDialect',
|
||||
'jdbc.driver': 'com.mysql.jdbc.Driver',
|
||||
'jdbc.user' : 'hibernateormtest',
|
||||
'jdbc.pass' : 'hibernateormtest',
|
||||
'jdbc.url' : 'jdbc:mysql://localhost/hibernate_orm_test'
|
||||
],
|
||||
mysql_docker : [
|
||||
'db.dialect' : 'org.hibernate.dialect.MySQL57Dialect',
|
||||
'db.dialect' : 'org.hibernate.dialect.MySQLDialect',
|
||||
'jdbc.driver': 'com.mysql.jdbc.Driver',
|
||||
'jdbc.user' : 'hibernate_orm_test',
|
||||
'jdbc.pass' : 'hibernate_orm_test',
|
||||
'jdbc.url' : 'jdbc:mysql://127.0.0.1/hibernate_orm_test?useSSL=false'
|
||||
],
|
||||
mariadb : [
|
||||
'db.dialect' : 'org.hibernate.dialect.MariaDB103Dialect',
|
||||
'db.dialect' : 'org.hibernate.dialect.MariaDBDialect',
|
||||
'jdbc.driver': 'org.mariadb.jdbc.Driver',
|
||||
'jdbc.user' : 'hibernate_orm_test',
|
||||
'jdbc.pass' : 'hibernate_orm_test',
|
||||
'jdbc.url' : 'jdbc:mariadb://127.0.0.1/hibernate_orm_test'
|
||||
],
|
||||
mariadb_ci : [
|
||||
'db.dialect' : 'org.hibernate.dialect.MariaDBDialect',
|
||||
'jdbc.driver': 'org.mariadb.jdbc.Driver',
|
||||
'jdbc.user' : 'root',
|
||||
'jdbc.pass' : 'hibernate_orm_test',
|
||||
'jdbc.url' : 'jdbc:mariadb://' + dbHost + '/hibernate_orm_test'
|
||||
],
|
||||
postgis : [
|
||||
'db.dialect' : 'org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect',
|
||||
'jdbc.driver': 'org.postgresql.Driver',
|
||||
|
@ -75,7 +90,7 @@ ext {
|
|||
'jdbc.url' : 'jdbc:postgresql:hibernate_orm_test'
|
||||
],
|
||||
oracle : [
|
||||
'db.dialect' : 'org.hibernate.dialect.Oracle10gDialect',
|
||||
'db.dialect' : 'org.hibernate.dialect.OracleDialect',
|
||||
'jdbc.driver': 'oracle.jdbc.OracleDriver',
|
||||
'jdbc.user' : 'hibernate_orm_test',
|
||||
'jdbc.pass' : 'hibernate_orm_test',
|
||||
|
@ -85,19 +100,33 @@ ext {
|
|||
// After registering to get access (see instructions at above link), start it for testing with:
|
||||
// docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 --name ORCLCDB -p 1521:1521 store/oracle/database-enterprise:12.2.0.1-slim
|
||||
oracle_docker : [
|
||||
'db.dialect' : 'org.hibernate.dialect.Oracle12cDialect',
|
||||
'db.dialect' : 'org.hibernate.dialect.OracleDialect',
|
||||
'jdbc.driver': 'oracle.jdbc.OracleDriver',
|
||||
'jdbc.user' : 'sys as sysdba',
|
||||
'jdbc.pass' : 'Oradoc_db1',
|
||||
'jdbc.url' : 'jdbc:oracle:thin:@localhost:1521:ORCLCDB'
|
||||
],
|
||||
oracle_ci : [
|
||||
'db.dialect' : 'org.hibernate.dialect.OracleDialect',
|
||||
'jdbc.driver': 'oracle.jdbc.OracleDriver',
|
||||
'jdbc.user' : 'SYSTEM',
|
||||
'jdbc.pass' : 'Oracle18',
|
||||
'jdbc.url' : 'jdbc:oracle:thin:@' + dbHost + ':1521:XE'
|
||||
],
|
||||
mssql : [
|
||||
'db.dialect' : 'org.hibernate.dialect.SQLServer2012Dialect',
|
||||
'db.dialect' : 'org.hibernate.dialect.SQLServerDialect',
|
||||
'jdbc.driver': 'com.microsoft.sqlserver.jdbc.SQLServerDriver',
|
||||
'jdbc.user' : 'hibernate_orm_test',
|
||||
'jdbc.pass' : 'hibernate_orm_test',
|
||||
'jdbc.url' : 'jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=hibernate_orm_test'
|
||||
],
|
||||
mssql_ci : [
|
||||
'db.dialect' : 'org.hibernate.dialect.SQLServerDialect',
|
||||
'jdbc.driver': 'com.microsoft.sqlserver.jdbc.SQLServerDriver',
|
||||
'jdbc.user' : 'sa',
|
||||
'jdbc.pass' : 'Hibernate_orm_test',
|
||||
'jdbc.url' : 'jdbc:sqlserver://' + dbHost + ';databaseName=hibernate_orm_test'
|
||||
],
|
||||
informix : [
|
||||
'db.dialect' : 'org.hibernate.dialect.InformixDialect',
|
||||
'jdbc.driver': 'com.informix.jdbc.IfxDriver',
|
||||
|
@ -112,6 +141,13 @@ ext {
|
|||
'jdbc.pass' : 'db2inst1-pwd',
|
||||
'jdbc.url' : 'jdbc:db2://127.0.0.1:50000/hibern8'
|
||||
],
|
||||
db2_ci : [
|
||||
'db.dialect' : 'org.hibernate.dialect.DB2Dialect',
|
||||
'jdbc.driver': 'com.ibm.db2.jcc.DB2Driver',
|
||||
'jdbc.user' : 'orm_test',
|
||||
'jdbc.pass' : 'orm_test',
|
||||
'jdbc.url' : 'jdbc:db2://' + dbHost + ':50000/orm_test'
|
||||
],
|
||||
hana : [
|
||||
'db.dialect' : 'org.hibernate.dialect.HANAColumnStoreDialect',
|
||||
'jdbc.driver': 'com.sap.db.jdbc.Driver',
|
||||
|
@ -134,7 +170,7 @@ ext {
|
|||
'jdbc.url' : 'jdbc:sap://localhost:39015/'
|
||||
],
|
||||
cockroachdb : [
|
||||
'db.dialect' : 'org.hibernate.dialect.CockroachDB192Dialect',
|
||||
'db.dialect' : 'org.hibernate.dialect.CockroachDialect',
|
||||
// CockroachDB uses the same pgwire protocol as PostgreSQL, so the driver is the same.
|
||||
'jdbc.driver': 'org.postgresql.Driver',
|
||||
'jdbc.user' : 'root',
|
||||
|
|
|
@ -111,10 +111,10 @@ dependencies {
|
|||
testRuntime( libraries.hana )
|
||||
testRuntime( libraries.cockroachdb )
|
||||
|
||||
if ( db.equalsIgnoreCase( 'oracle' ) || db.equalsIgnoreCase( 'oracle_docker' ) ) {
|
||||
if ( db.startsWith( 'oracle' ) ) {
|
||||
testRuntime( libraries.oracle )
|
||||
}
|
||||
else if ( db.equalsIgnoreCase( 'db2' ) ) {
|
||||
else if ( db.startsWith( 'db2' ) ) {
|
||||
testRuntime( libraries.db2 )
|
||||
}
|
||||
else if ( db.equalsIgnoreCase( 'hana' ) ) {
|
||||
|
|
|
@ -121,7 +121,7 @@ PLUS : '+';
|
|||
MINUS : '-';
|
||||
ASTERISK : '*';
|
||||
SLASH : '/';
|
||||
PERCENT : '%';
|
||||
PERCENT_OP : '%';
|
||||
AMPERSAND : '&';
|
||||
SEMICOLON : ';';
|
||||
COLON : ':';
|
||||
|
@ -176,6 +176,7 @@ END : [eE] [nN] [dD];
|
|||
ENTRY : [eE] [nN] [tT] [rR] [yY];
|
||||
ESCAPE : [eE] [sS] [cC] [aA] [pP] [eE];
|
||||
EVERY : [eE] [vV] [eE] [rR] [yY];
|
||||
EXCEPT : [eE] [xX] [cC] [eE] [pP] [tT];
|
||||
EXISTS : [eE] [xX] [iI] [sS] [tT] [sS];
|
||||
EXP : [eE] [xX] [pP];
|
||||
EXTRACT : [eE] [xX] [tT] [rR] [aA] [cC] [tT];
|
||||
|
@ -197,6 +198,7 @@ INDEX : [iI] [nN] [dD] [eE] [xX];
|
|||
INNER : [iI] [nN] [nN] [eE] [rR];
|
||||
INSERT : [iI] [nN] [sS] [eE] [rR] [tT];
|
||||
INSTANT : [iI] [nN] [sS] [tT] [aA] [nN] [tT];
|
||||
INTERSECT : [iI] [nN] [tT] [eE] [rR] [sS] [eE] [cC] [tT];
|
||||
INTO : [iI] [nN] [tT] [oO];
|
||||
IS : [iI] [sS];
|
||||
JOIN : [jJ] [oO] [iI] [nN];
|
||||
|
@ -230,6 +232,7 @@ MINUTE : [mM] [iI] [nN] [uU] [tT] [eE];
|
|||
MOD : [mM] [oO] [dD];
|
||||
MONTH : [mM] [oO] [nN] [tT] [hH];
|
||||
NANOSECOND : [nN] [aA] [nN] [oO] [sS] [eE] [cC] [oO] [nN] [dD];
|
||||
NEXT : [nN] [eE] [xX] [tT];
|
||||
NEW : [nN] [eE] [wW];
|
||||
NOT : [nN] [oO] [tT];
|
||||
NULLIF : [nN] [uU] [lL] [lL] [iI] [fF];
|
||||
|
@ -239,11 +242,13 @@ OF : [oO] [fF];
|
|||
OFFSET : [oO] [fF] [fF] [sS] [eE] [tT];
|
||||
OFFSET_DATETIME : [oO] [fF] [fF] [sS] [eE] [tT] '_' [dD] [aA] [tT] [eE] [tT] [iI] [mM] [eE];
|
||||
ON : [oO] [nN];
|
||||
ONLY : [oO] [nN] [lL] [yY];
|
||||
OR : [oO] [rR];
|
||||
ORDER : [oO] [rR] [dD] [eE] [rR];
|
||||
OUTER : [oO] [uU] [tT] [eE] [rR];
|
||||
OVERLAY : [oO] [vV] [eE] [rR] [lL] [aA] [yY];
|
||||
PAD : [pP] [aA] [dD];
|
||||
PERCENT : [pP] [eE] [rR] [cC] [eE] [nN] [tT];
|
||||
PLACING : [pP] [lL] [aA] [cC] [iI] [nN] [gG];
|
||||
POSITION : [pP] [oO] [sS] [iI] [tT] [iI] [oO] [nN];
|
||||
POWER : [pP] [oO] [wW] [eE] [rR];
|
||||
|
@ -252,6 +257,8 @@ REPLACE : [rR] [eE] [pP] [lL] [aA] [cC] [eE];
|
|||
RIGHT : [rR] [iI] [gG] [hH] [tT];
|
||||
ROLLUP : [rR] [oO] [lL] [lL] [uU] [pP];
|
||||
ROUND : [rR] [oO] [uU] [nN] [dD];
|
||||
ROWS : [rR] [oO] [wW] [sS];
|
||||
ROW : [rR] [oO] [wW];
|
||||
SECOND : [sS] [eE] [cC] [oO] [nN] [dD];
|
||||
SELECT : [sS] [eE] [lL] [eE] [cC] [tT];
|
||||
SET : [sS] [eE] [tT];
|
||||
|
@ -263,6 +270,7 @@ STR : [sS] [tT] [rR];
|
|||
SUBSTRING : [sS] [uU] [bB] [sS] [tT] [rR] [iI] [nN] [gG];
|
||||
SUM : [sS] [uU] [mM];
|
||||
THEN : [tT] [hH] [eE] [nN];
|
||||
TIES : [tT] [iI] [eE] [sS];
|
||||
TIME : [tT] [iI] [mM] [eE];
|
||||
TIMESTAMP : [tT] [iI] [mM] [eE] [sS] [tT] [aA] [mM] [pP];
|
||||
TIMEZONE_HOUR : [tT] [iI] [mM] [eE] [zZ] [oO] [nN] [eE] '_' [hH] [oO] [uU] [rR];
|
||||
|
@ -271,6 +279,7 @@ TRAILING : [tT] [rR] [aA] [iI] [lL] [iI] [nN] [gG];
|
|||
TREAT : [tT] [rR] [eE] [aA] [tT];
|
||||
TRIM : [tT] [rR] [iI] [mM];
|
||||
TYPE : [tT] [yY] [pP] [eE];
|
||||
UNION : [uU] [nN] [iI] [oO] [nN];
|
||||
UPDATE : [uU] [pP] [dD] [aA] [tT] [eE];
|
||||
UPPER : [uU] [pP] [pP] [eE] [rR];
|
||||
VALUE : [vV] [aA] [lL] [uU] [eE];
|
||||
|
|
|
@ -28,11 +28,11 @@ statement
|
|||
;
|
||||
|
||||
selectStatement
|
||||
: querySpec
|
||||
: queryExpression
|
||||
;
|
||||
|
||||
subQuery
|
||||
: querySpec
|
||||
: queryExpression
|
||||
;
|
||||
|
||||
dmlTarget
|
||||
|
@ -56,7 +56,7 @@ assignment
|
|||
;
|
||||
|
||||
insertStatement
|
||||
: INSERT INTO? dmlTarget targetFieldsSpec (querySpec | valuesList)
|
||||
: INSERT INTO? dmlTarget targetFieldsSpec (queryExpression | valuesList)
|
||||
;
|
||||
|
||||
targetFieldsSpec
|
||||
|
@ -74,9 +74,30 @@ values
|
|||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// QUERY SPEC - general structure of root sqm or sub sqm
|
||||
|
||||
queryExpression
|
||||
: queryGroup queryOrder?
|
||||
;
|
||||
|
||||
queryGroup
|
||||
: querySpec # QuerySpecQueryGroup
|
||||
| LEFT_PAREN queryGroup RIGHT_PAREN # NestedQueryGroup
|
||||
| queryGroup queryOrder? (setOperator (querySpec | LEFT_PAREN queryGroup RIGHT_PAREN))+ # SetQueryGroup
|
||||
;
|
||||
|
||||
setOperator
|
||||
: UNION ALL?
|
||||
| INTERSECT ALL?
|
||||
| EXCEPT ALL?
|
||||
;
|
||||
|
||||
queryOrder
|
||||
: orderByClause limitClause? offsetClause? fetchClause?
|
||||
;
|
||||
|
||||
querySpec
|
||||
: selectClause fromClause? whereClause? ( groupByClause havingClause? )? orderByClause? limitClause? offsetClause?
|
||||
| fromClause whereClause? ( groupByClause havingClause? )? selectClause? orderByClause? limitClause? offsetClause?
|
||||
// TODO: add with clause
|
||||
: selectClause fromClause? whereClause? ( groupByClause havingClause? )?
|
||||
| fromClause whereClause? ( groupByClause havingClause? )? selectClause?
|
||||
;
|
||||
|
||||
|
||||
|
@ -340,16 +361,27 @@ orderingSpecification
|
|||
// LIMIT/OFFSET clause
|
||||
|
||||
limitClause
|
||||
: LIMIT parameterOrNumberLiteral
|
||||
: LIMIT parameterOrIntegerLiteral
|
||||
;
|
||||
|
||||
offsetClause
|
||||
: OFFSET parameterOrNumberLiteral
|
||||
: OFFSET parameterOrIntegerLiteral (ROW | ROWS)?
|
||||
;
|
||||
|
||||
fetchClause
|
||||
: FETCH (FIRST | NEXT) (parameterOrIntegerLiteral | parameterOrNumberLiteral PERCENT) (ROW | ROWS) (ONLY | WITH TIES)
|
||||
;
|
||||
|
||||
parameterOrIntegerLiteral
|
||||
: parameter
|
||||
| INTEGER_LITERAL
|
||||
;
|
||||
|
||||
parameterOrNumberLiteral
|
||||
: parameter
|
||||
| INTEGER_LITERAL
|
||||
| FLOAT_LITERAL
|
||||
| DOUBLE_LITERAL
|
||||
;
|
||||
|
||||
|
||||
|
@ -427,7 +459,7 @@ primaryExpression
|
|||
|
||||
multiplicativeOperator
|
||||
: SLASH
|
||||
| PERCENT
|
||||
| PERCENT_OP
|
||||
| ASTERISK
|
||||
;
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The kind of CTE search clause.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public enum CteSearchClauseKind {
|
||||
/**
|
||||
* Use depth first for a recursive CTE.
|
||||
*/
|
||||
DEPTH_FIRST,
|
||||
/**
|
||||
* Use breadth first for a recursive CTE.
|
||||
*/
|
||||
BREADTH_FIRST;
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* The kind of fetch to use for the FETCH clause.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public enum FetchClauseType {
|
||||
/**
|
||||
* Exact row count like for LIMIT clause or FETCH FIRST x ROWS ONLY.
|
||||
*/
|
||||
ROWS_ONLY,
|
||||
/**
|
||||
* Also fetches ties if the last value is not unique FETCH FIRST x ROWS WITH TIES.
|
||||
*/
|
||||
ROWS_WITH_TIES,
|
||||
/**
|
||||
* Row count in percent FETCH FIRST x PERCENT ROWS ONLY.
|
||||
*/
|
||||
PERCENT_ONLY,
|
||||
/**
|
||||
* Also fetches ties if the last value is not unique FETCH FIRST x PERCENT ROWS WITH TIES.
|
||||
*/
|
||||
PERCENT_WITH_TIES;
|
||||
}
|
|
@ -75,6 +75,14 @@ public class LockOptions implements Serializable {
|
|||
this.lockMode = lockMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the lock options are empty.
|
||||
*
|
||||
* @return If the lock options is equivalent to {@link LockOptions#NONE}.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return lockMode == LockMode.NONE && timeout == WAIT_FOREVER && followOnLocking == null && !scope && !hasAliasSpecificLockModes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the overall lock mode in effect for this set of options.
|
||||
|
@ -329,4 +337,30 @@ public class LockOptions implements Serializable {
|
|||
destination.setFollowOnLocking( source.getFollowOnLocking() );
|
||||
return destination;
|
||||
}
|
||||
|
||||
public boolean isCompatible(LockOptions that) {
|
||||
if ( that == null ) {
|
||||
return isEmpty();
|
||||
}
|
||||
else if ( this == that ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( timeout != that.timeout ) {
|
||||
return false;
|
||||
}
|
||||
if ( scope != that.scope ) {
|
||||
return false;
|
||||
}
|
||||
if ( lockMode != that.lockMode ) {
|
||||
return false;
|
||||
}
|
||||
if ( aliasSpecificLockModes != null ?
|
||||
!aliasSpecificLockModes.equals( that.aliasSpecificLockModes ) :
|
||||
that.aliasSpecificLockModes != null ) {
|
||||
return false;
|
||||
}
|
||||
return followOnLocking != null ? followOnLocking.equals( that.followOnLocking ) : that.followOnLocking == null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* The order of null.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public enum NullOrdering {
|
||||
/**
|
||||
* Null is treated as the smallest value.
|
||||
*/
|
||||
SMALLEST,
|
||||
|
||||
/**
|
||||
* Null is treated as the greatest value.
|
||||
*/
|
||||
GREATEST,
|
||||
|
||||
/**
|
||||
* Null is always ordered first.
|
||||
*/
|
||||
FIRST,
|
||||
|
||||
/**
|
||||
* Null is always ordered last.
|
||||
*/
|
||||
LAST;
|
||||
}
|
|
@ -15,17 +15,53 @@ public enum NullPrecedence {
|
|||
/**
|
||||
* Null precedence not specified. Relies on the RDBMS implementation.
|
||||
*/
|
||||
NONE,
|
||||
NONE {
|
||||
@Override
|
||||
public boolean isDefaultOrdering(SortOrder sortOrder, NullOrdering nullOrdering) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Null values appear at the beginning of the sorted collection.
|
||||
*/
|
||||
FIRST,
|
||||
FIRST {
|
||||
@Override
|
||||
public boolean isDefaultOrdering(SortOrder sortOrder, NullOrdering nullOrdering) {
|
||||
switch ( nullOrdering ) {
|
||||
case FIRST:
|
||||
return true;
|
||||
case SMALLEST:
|
||||
return sortOrder == SortOrder.ASCENDING;
|
||||
case GREATEST:
|
||||
return sortOrder == SortOrder.DESCENDING;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Null values appear at the end of the sorted collection.
|
||||
*/
|
||||
LAST;
|
||||
LAST {
|
||||
@Override
|
||||
public boolean isDefaultOrdering(SortOrder sortOrder, NullOrdering nullOrdering) {
|
||||
switch ( nullOrdering ) {
|
||||
case LAST:
|
||||
return true;
|
||||
case SMALLEST:
|
||||
return sortOrder == SortOrder.DESCENDING;
|
||||
case GREATEST:
|
||||
return sortOrder == SortOrder.ASCENDING;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Is this null precedence the default for the given sort order and null ordering.
|
||||
*/
|
||||
public abstract boolean isDefaultOrdering(SortOrder sortOrder, NullOrdering nullOrdering);
|
||||
|
||||
/**
|
||||
* Interprets a string representation of a NullPrecedence, returning {@code null} by default. For
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The SQL set operators.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public enum SetOperator {
|
||||
/**
|
||||
* Union of sets that removes duplicate rows.
|
||||
*/
|
||||
UNION("union"),
|
||||
/**
|
||||
* Union of bags that retains all elements.
|
||||
*/
|
||||
UNION_ALL("union all"),
|
||||
/**
|
||||
* Intersection of sets that removes duplicate rows.
|
||||
*/
|
||||
INTERSECT("intersect"),
|
||||
/**
|
||||
* Intersection of bags that retains duplicate matches.
|
||||
*/
|
||||
INTERSECT_ALL("intersect all"),
|
||||
/**
|
||||
* Exclusion of set elements of the set on the right-hand side.
|
||||
*/
|
||||
EXCEPT("except"),
|
||||
/**
|
||||
* Exclusion of bag elements of the bag on the right-hand side that retains duplicates.
|
||||
*/
|
||||
EXCEPT_ALL("except all");
|
||||
|
||||
private final String sqlString;
|
||||
|
||||
private SetOperator(String sqlString) {
|
||||
this.sqlString = sqlString;
|
||||
}
|
||||
|
||||
public String sqlString() {
|
||||
return sqlString;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ import org.hibernate.engine.config.spi.StandardConverters;
|
|||
import org.hibernate.engine.jdbc.*;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.env.spi.*;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
|
@ -39,6 +40,10 @@ import org.hibernate.procedure.spi.CallableStatementSupport;
|
|||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorHANADatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
import org.hibernate.tool.schema.internal.StandardTableExporter;
|
||||
|
@ -821,6 +826,17 @@ public abstract class AbstractHANADialect extends Dialect {
|
|||
CommonFunctionFactory.currentUtcdatetimetimestamp( queryEngine );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, org.hibernate.sql.ast.tree.Statement statement) {
|
||||
return new HANASqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* HANA has no extract() function, but we can emulate
|
||||
* it using the appropriate named functions instead of
|
||||
|
@ -1158,11 +1174,6 @@ public abstract class AbstractHANADialect extends Dialect {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dropConstraints() {
|
||||
return false;
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.dialect;
|
|||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.NullOrdering;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||
|
@ -223,6 +224,11 @@ abstract class AbstractTransactSQLDialect extends Dialect {
|
|||
return GroupByConstantRenderingStrategy.COLUMN_REFERENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NullOrdering getNullOrdering() {
|
||||
return NullOrdering.SMALLEST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
|
||||
EntityMappingType entityDescriptor,
|
||||
|
@ -254,11 +260,6 @@ abstract class AbstractTransactSQLDialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsExistsInSelect() {
|
||||
return false;
|
||||
|
|
|
@ -16,9 +16,15 @@ import org.hibernate.dialect.pagination.LimitLimitHandler;
|
|||
import org.hibernate.dialect.sequence.CUBRIDSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorCUBRIDDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
|
||||
|
@ -238,11 +244,6 @@ public class CUBRIDDialect extends Dialect {
|
|||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCurrentTimestampSelection() {
|
||||
return true;
|
||||
|
@ -273,6 +274,17 @@ public class CUBRIDDialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new CUBRIDSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public LimitHandler getLimitHandler() {
|
||||
return LimitLimitHandler.INSTANCE;
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for CUBRID.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class CUBRIDSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public CUBRIDSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
renderCombinedLimitClause( queryPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// CUBRID does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// CUBRID does not support this, but it can be emulated
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ import org.hibernate.dialect.pagination.LimitHandler;
|
|||
import org.hibernate.dialect.pagination.TopLimitHandler;
|
||||
import org.hibernate.dialect.sequence.CacheSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.hibernate.exception.DataException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
|
@ -27,6 +28,11 @@ import org.hibernate.query.TemporalUnit;
|
|||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.sql.CacheJoinFragment;
|
||||
import org.hibernate.sql.JoinFragment;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
|
@ -277,6 +283,17 @@ public class CacheDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new CacheSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// LIMIT support (ala TOP) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Cache.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class CacheSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public CacheSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitSqlSelections(SelectClause selectClause) {
|
||||
renderTopClause( (QuerySpec) getQueryPartStack().getCurrent(), true );
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderTopClause(QuerySpec querySpec, boolean addOffset) {
|
||||
assertRowsOnlyFetchClauseType( querySpec );
|
||||
super.renderTopClause( querySpec, addOffset );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchPlusOffsetExpression(
|
||||
Expression fetchClauseExpression,
|
||||
Expression offsetClauseExpression,
|
||||
int offset) {
|
||||
renderFetchPlusOffsetExpressionAsSingleParameter( fetchClauseExpression, offsetClauseExpression, offset );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
// Cache only supports the TOP clause
|
||||
if ( !queryPart.isRoot() && queryPart.getOffsetClauseExpression() != null ) {
|
||||
throw new IllegalArgumentException( "Can't emulate offset clause in subquery" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Cache does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Cache does not support this, but it can be emulated
|
||||
}
|
||||
}
|
|
@ -12,8 +12,14 @@ import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
|
|||
import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
import java.sql.Types;
|
||||
|
@ -169,11 +175,6 @@ public class CockroachDialect extends Dialect {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNoColumnsInsertString() {
|
||||
return "default values";
|
||||
|
@ -209,6 +210,17 @@ public class CockroachDialect extends Dialect {
|
|||
return "select sequence_name, sequence_schema, sequence_catalog, start_value, minimum_value, maximum_value, increment from information_schema.sequences";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new CockroachSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsNationalizedTypes() {
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Cockroach.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class CockroachSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public CockroachSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
// Check if current query part is already row numbering to avoid infinite recursion
|
||||
return useOffsetFetchClause( queryPart ) && getQueryPartForRowNumbering() != queryPart
|
||||
&& !isRowsOnlyFetchClauseType( queryPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQueryGroup(QueryGroup queryGroup) {
|
||||
if ( shouldEmulateFetchClause( queryGroup ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( queryGroup, true );
|
||||
}
|
||||
else {
|
||||
super.visitQueryGroup( queryGroup );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQuerySpec(QuerySpec querySpec) {
|
||||
if ( shouldEmulateFetchClause( querySpec ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( querySpec, true );
|
||||
}
|
||||
else {
|
||||
super.visitQuerySpec( querySpec );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||
renderLimitOffsetClause( queryPart );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Cockroach does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Cockroach does not support this, but it can be emulated
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import org.hibernate.dialect.sequence.SequenceSupport;
|
|||
import org.hibernate.dialect.unique.DB2UniqueDelegate;
|
||||
import org.hibernate.dialect.unique.UniqueDelegate;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
|
@ -30,11 +31,13 @@ import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
|||
import org.hibernate.query.CastType;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.GlobalTemporaryTableStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||
import org.hibernate.query.sqm.mutation.internal.cte.CteStrategy;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorDB2DatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
|
@ -92,7 +95,7 @@ public class DB2Dialect extends Dialect {
|
|||
// registerColumnType( Types.DECIMAL, "decimal($p,$s)" );
|
||||
registerColumnType( Types.NUMERIC, "decimal($p,$s)" );
|
||||
|
||||
if ( getVersion()<1100 ) {
|
||||
if ( getVersion() < 1100 ) {
|
||||
registerColumnType( Types.BINARY, "varchar($l) for bit data" ); //should use 'binary' since version 11
|
||||
registerColumnType( Types.BINARY, 254, "char($l) for bit data" ); //should use 'binary' since version 11
|
||||
registerColumnType( Types.VARBINARY, "varchar($l) for bit data" ); //should use 'varbinary' since version 11
|
||||
|
@ -407,11 +410,6 @@ public class DB2Dialect extends Dialect {
|
|||
return "nullif(" + literal + ", " + literal + ')';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
|
||||
return col;
|
||||
|
@ -437,47 +435,7 @@ public class DB2Dialect extends Dialect {
|
|||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
|
||||
EntityMappingType rootEntityDescriptor,
|
||||
RuntimeModelCreationContext runtimeModelCreationContext) {
|
||||
|
||||
if ( getVersion() >= 970 ) {
|
||||
// Starting in DB2 9.7, "real" global temporary tables that can be shared between sessions
|
||||
// are supported; (obviously) data is not shared between sessions.
|
||||
return new GlobalTemporaryTableStrategy(
|
||||
new IdTable( rootEntityDescriptor, name -> "HT_" + name, this ),
|
||||
() -> new TempIdTableExporter( false, this::getTypeName ) {
|
||||
@Override
|
||||
protected String getCreateOptions() {
|
||||
return "not logged";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN,
|
||||
runtimeModelCreationContext.getSessionFactory()
|
||||
);
|
||||
}
|
||||
|
||||
return super.getFallbackSqmMutationStrategy( rootEntityDescriptor, runtimeModelCreationContext );
|
||||
// // Prior to DB2 9.7, "real" global temporary tables that can be shared between sessions
|
||||
// // are *not* supported; even though the DB2 command says to declare a "global" temp table
|
||||
// // Hibernate treats it as a "local" temp table.
|
||||
// return new LocalTemporaryTableBulkIdStrategy(
|
||||
// new IdTableSupportStandardImpl() {
|
||||
// @Override
|
||||
// public String generateIdTableName(String baseName) {
|
||||
// return "session." + super.generateIdTableName( baseName );
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getCreateIdTableCommand() {
|
||||
// return "declare global temporary table";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getCreateIdTableStatementOptions() {
|
||||
// return "not logged";
|
||||
// }
|
||||
// },
|
||||
// AfterUseAction.DROP,
|
||||
// null
|
||||
// );
|
||||
return new CteStrategy( rootEntityDescriptor, runtimeModelCreationContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -639,6 +597,17 @@ public class DB2Dialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new DB2SqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle DB2 "support" for null precedence...
|
||||
*
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.MutationStatement;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.insert.InsertStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.update.UpdateStatement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for DB2.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class DB2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public DB2SqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
// Percent fetches or ties fetches aren't supported in DB2
|
||||
// According to LegacyDB2LimitHandler, variable limit also isn't supported before 11.1
|
||||
// Check if current query part is already row numbering to avoid infinite recursion
|
||||
return getQueryPartForRowNumbering() != queryPart && (
|
||||
useOffsetFetchClause( queryPart ) && !isRowsOnlyFetchClauseType( queryPart )
|
||||
|| getDialect().getVersion() < 1110 && ( queryPart.isRoot() && hasLimit() || !( queryPart.getFetchClauseExpression() instanceof Literal ) )
|
||||
);
|
||||
}
|
||||
|
||||
protected boolean supportsOffsetClause() {
|
||||
return getDialect().getVersion() >= 1110;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQueryGroup(QueryGroup queryGroup) {
|
||||
final boolean emulateFetchClause = shouldEmulateFetchClause( queryGroup );
|
||||
if ( emulateFetchClause || hasOffset( queryGroup ) && !supportsOffsetClause() ) {
|
||||
emulateFetchOffsetWithWindowFunctions( queryGroup, emulateFetchClause );
|
||||
}
|
||||
else {
|
||||
super.visitQueryGroup( queryGroup );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQuerySpec(QuerySpec querySpec) {
|
||||
final boolean emulateFetchClause = shouldEmulateFetchClause( querySpec );
|
||||
if ( emulateFetchClause || hasOffset( querySpec ) && !supportsOffsetClause() ) {
|
||||
emulateFetchOffsetWithWindowFunctions( querySpec, emulateFetchClause );
|
||||
}
|
||||
else {
|
||||
super.visitQuerySpec( querySpec );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||
if ( !hasOffset( queryPart ) || supportsOffsetClause() ) {
|
||||
renderOffsetFetchClause( queryPart, true );
|
||||
}
|
||||
else if ( queryPart.isRoot() && hasLimit() ) {
|
||||
renderFetch( getLimitParameter(), null, FetchClauseType.ROWS_ONLY );
|
||||
}
|
||||
else if ( queryPart.getFetchClauseExpression() != null ) {
|
||||
renderFetch( queryPart.getFetchClauseExpression(), null, queryPart.getFetchClauseType() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitDeleteStatementOnly(DeleteStatement statement) {
|
||||
final boolean closeWrapper = renderReturningClause( statement );
|
||||
super.visitDeleteStatementOnly( statement );
|
||||
if ( closeWrapper ) {
|
||||
appendSql( ')' );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitUpdateStatementOnly(UpdateStatement statement) {
|
||||
final boolean closeWrapper = renderReturningClause( statement );
|
||||
super.visitUpdateStatementOnly( statement );
|
||||
if ( closeWrapper ) {
|
||||
appendSql( ')' );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitInsertStatementOnly(InsertStatement statement) {
|
||||
final boolean closeWrapper = renderReturningClause( statement );
|
||||
super.visitInsertStatementOnly( statement );
|
||||
if ( closeWrapper ) {
|
||||
appendSql( ')' );
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean renderReturningClause(MutationStatement statement) {
|
||||
final List<ColumnReference> returningColumns = statement.getReturningColumns();
|
||||
final int size = returningColumns.size();
|
||||
if ( size == 0 ) {
|
||||
return false;
|
||||
}
|
||||
appendSql( "select " );
|
||||
String separator = "";
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
appendSql( separator );
|
||||
appendSql( returningColumns.get( i ).getColumnExpression() );
|
||||
separator = ", ";
|
||||
}
|
||||
if ( statement instanceof DeleteStatement ) {
|
||||
appendSql( " from old table (" );
|
||||
}
|
||||
else {
|
||||
appendSql( " from final table (" );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitReturningColumns(MutationStatement mutationStatement) {
|
||||
// For DB2 we use #renderReturningClause to render a wrapper around the DML statement
|
||||
}
|
||||
|
||||
}
|
|
@ -15,10 +15,15 @@ import org.hibernate.dialect.pagination.LimitHandler;
|
|||
import org.hibernate.dialect.sequence.DB2iSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.NoSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.dialect.unique.DB2UniqueDelegate;
|
||||
import org.hibernate.dialect.unique.DefaultUniqueDelegate;
|
||||
import org.hibernate.dialect.unique.UniqueDelegate;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* An SQL dialect for DB2 for iSeries previously known as DB2/400.
|
||||
|
@ -90,10 +95,10 @@ public class DB2iDialect extends DB2Dialect {
|
|||
@Override
|
||||
public LimitHandler getLimitHandler() {
|
||||
if ( getIVersion() >= 730) {
|
||||
return LegacyDB2LimitHandler.INSTANCE;
|
||||
return FetchLimitHandler.INSTANCE;
|
||||
}
|
||||
else {
|
||||
return FetchLimitHandler.INSTANCE;
|
||||
return LegacyDB2LimitHandler.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,4 +111,15 @@ public class DB2iDialect extends DB2Dialect {
|
|||
return new DB2390IdentityColumnSupport();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new DB2iSqlAstTranslator<>( sessionFactory, statement, version );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for DB2i.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class DB2iSqlAstTranslator<T extends JdbcOperation> extends DB2SqlAstTranslator<T> {
|
||||
|
||||
private final int version;
|
||||
|
||||
public DB2iSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement, int version) {
|
||||
super( sessionFactory, statement );
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
// Percent fetches or ties fetches aren't supported in DB2 iSeries
|
||||
// According to LegacyDB2LimitHandler, variable limit also isn't supported before 7.1
|
||||
return getQueryPartForRowNumbering() != queryPart && (
|
||||
useOffsetFetchClause( queryPart ) && !isRowsOnlyFetchClauseType( queryPart )
|
||||
|| version < 710 && ( queryPart.isRoot() && hasLimit() || !( queryPart.getFetchClauseExpression() instanceof Literal ) )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsOffsetClause() {
|
||||
return version >= 710;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -18,7 +18,13 @@ import org.hibernate.dialect.sequence.DB2390SequenceSupport;
|
|||
import org.hibernate.dialect.sequence.NoSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* An SQL dialect for DB2 for z/OS, previously known as known as Db2 UDB for z/OS and Db2 UDB for z/OS and OS/390.
|
||||
|
@ -128,4 +134,15 @@ public class DB2zDialect extends DB2Dialect {
|
|||
pattern.append(")");
|
||||
return pattern.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new DB2zSqlAstTranslator<>( sessionFactory, statement, version );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for DB2z.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class DB2zSqlAstTranslator<T extends JdbcOperation> extends DB2SqlAstTranslator<T> {
|
||||
|
||||
private final int version;
|
||||
|
||||
public DB2zSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement, int version) {
|
||||
super( sessionFactory, statement );
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
// Percent fetches or ties fetches aren't supported in DB2 z/OS
|
||||
// Also, variable limit isn't supported before 12.0
|
||||
return getQueryPartForRowNumbering() != queryPart && (
|
||||
useOffsetFetchClause( queryPart ) && !isRowsOnlyFetchClauseType( queryPart )
|
||||
|| version < 1200 && queryPart.isRoot() && hasLimit()
|
||||
|| version < 1200 && queryPart.getFetchClauseExpression() != null && !( queryPart.getFetchClauseExpression() instanceof Literal )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsOffsetClause() {
|
||||
return version >= 1200;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,6 +23,7 @@ import org.hibernate.engine.jdbc.Size;
|
|||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
|
@ -39,6 +40,11 @@ import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
|||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.CaseFragment;
|
||||
import org.hibernate.sql.DerbyCaseFragment;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorDerbyDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
|
@ -202,6 +208,17 @@ public class DerbyDialect extends Dialect {
|
|||
.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new DerbySqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Derby doesn't have an extract() function, and has
|
||||
* no functions at all for calendaring, but we can
|
||||
|
@ -410,11 +427,6 @@ public class DerbyDialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCurrentTimestampSelection() {
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteContainer;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Derby.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class DerbySqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public DerbySqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCteContainer(CteContainer cteContainer) {
|
||||
if ( cteContainer.isWithRecursive() ) {
|
||||
throw new IllegalArgumentException( "Recursive CTEs can't be emulated" );
|
||||
}
|
||||
super.visitCteContainer( cteContainer );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Derby does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Derby does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
// Derby only supports the OFFSET and FETCH clause with ROWS
|
||||
assertRowsOnlyFetchClauseType( queryPart );
|
||||
if ( supportsOffsetFetchClause() ) {
|
||||
renderOffsetFetchClause( queryPart, true );
|
||||
}
|
||||
else if ( !getClauseStack().isEmpty() ) {
|
||||
throw new IllegalArgumentException( "Can't render offset and fetch clause for subquery" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchExpression(Expression fetchExpression) {
|
||||
if ( supportsParameterOffsetFetchExpression() ) {
|
||||
super.renderFetchExpression( fetchExpression );
|
||||
}
|
||||
else {
|
||||
renderExpressionAsLiteral( fetchExpression, getJdbcParameterBindings() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderOffsetExpression(Expression offsetExpression) {
|
||||
if ( supportsParameterOffsetFetchExpression() ) {
|
||||
super.renderOffsetExpression( offsetExpression );
|
||||
}
|
||||
else {
|
||||
renderExpressionAsLiteral( offsetExpression, getJdbcParameterBindings() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return !supportsOffsetFetchClause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsMaxRows() {
|
||||
return !supportsOffsetFetchClause();
|
||||
}
|
||||
|
||||
private boolean supportsParameterOffsetFetchExpression() {
|
||||
return getDialect().getVersion() >= 1060;
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
// Before version 10.5 Derby didn't support OFFSET and FETCH
|
||||
return getDialect().getVersion() >= 1050;
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@ import org.hibernate.LockMode;
|
|||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.NullOrdering;
|
||||
import org.hibernate.NullPrecedence;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.boot.model.TypeContributions;
|
||||
|
@ -1877,16 +1878,14 @@ public abstract class Dialect implements ConversionContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Does this dialect support UNION ALL, which is generally a faster
|
||||
* variant of UNION?
|
||||
* Does this dialect support UNION ALL.
|
||||
*
|
||||
* @return True if UNION ALL is supported; false otherwise.
|
||||
*/
|
||||
public boolean supportsUnionAll() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// miscellaneous support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
|
@ -2690,6 +2689,15 @@ public abstract class Dialect implements ConversionContext {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ordering of null.
|
||||
*
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public NullOrdering getNullOrdering() {
|
||||
return NullOrdering.GREATEST;
|
||||
}
|
||||
|
||||
public boolean supportsNullPrecedence() {
|
||||
return true;
|
||||
}
|
||||
|
@ -2705,7 +2713,9 @@ public abstract class Dialect implements ConversionContext {
|
|||
* if expression has not been explicitly specified.
|
||||
* @param nulls Nulls precedence. Default value: {@link NullPrecedence#NONE}.
|
||||
* @return Renders single element of {@code ORDER BY} clause.
|
||||
* @deprecated todo (6.0): remove?
|
||||
*/
|
||||
@Deprecated
|
||||
public String renderOrderByElement(String expression, String collation, String order, NullPrecedence nulls) {
|
||||
final StringBuilder orderByElement = new StringBuilder( expression );
|
||||
if ( collation != null ) {
|
||||
|
@ -2772,7 +2782,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
* false otherwise.
|
||||
* @since 3.2
|
||||
*/
|
||||
public boolean supportsSubselectAsInPredicateLHS() {
|
||||
public boolean supportsSubselectAsInPredicateLHS() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2980,7 +2990,9 @@ public abstract class Dialect implements ConversionContext {
|
|||
* @param expression The expression to negate
|
||||
*
|
||||
* @return The negated expression
|
||||
* @deprecated todo (6.0): Remove
|
||||
*/
|
||||
@Deprecated
|
||||
public String getNotExpression(String expression) {
|
||||
return "not " + expression;
|
||||
}
|
||||
|
@ -3053,7 +3065,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
*/
|
||||
public String getQueryHintString(String query, List<String> hintList) {
|
||||
final String hints = String.join( ", ", hintList );
|
||||
return StringHelper.isEmpty( hints) ? query : getQueryHintString( query, hints);
|
||||
return StringHelper.isEmpty( hints ) ? query : getQueryHintString( query, hints);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3215,14 +3227,6 @@ public abstract class Dialect implements ConversionContext {
|
|||
return String.format( "\'%s\'", escapeLiteral( literal ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the collate clause for the given collation name to the SQL appender.
|
||||
*/
|
||||
public void appendCollate(SqlAppender sqlAppender, String collationName) {
|
||||
sqlAppender.appendSql( " collate " );
|
||||
sqlAppender.appendSql( collationName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the JDBC {@link java.sql.Connection} supports creating LOBs via {@link Connection#createBlob()},
|
||||
* {@link Connection#createNClob()} or {@link Connection#createClob()}.
|
||||
|
@ -3249,17 +3253,16 @@ public abstract class Dialect implements ConversionContext {
|
|||
*/
|
||||
public String addSqlHintOrComment(
|
||||
String sql,
|
||||
// QueryParameters parameters,
|
||||
QueryOptions queryOptions,
|
||||
boolean commentsEnabled) {
|
||||
|
||||
// Keep this here, rather than moving to Select. Some Dialects may need the hint to be appended to the very
|
||||
// end or beginning of the finalized SQL statement, so wait until everything is processed.
|
||||
// if ( parameters.getQueryHints() != null && parameters.getQueryHints().size() > 0 ) {
|
||||
// sql = getQueryHintString( sql, parameters.getQueryHints() );
|
||||
// }
|
||||
// if ( commentsEnabled && parameters.getComment() != null ){
|
||||
// sql = prependComment( sql, parameters.getComment() );
|
||||
// }
|
||||
if ( queryOptions.getDatabaseHints() != null && queryOptions.getDatabaseHints().size() > 0 ) {
|
||||
sql = getQueryHintString( sql, queryOptions.getDatabaseHints() );
|
||||
}
|
||||
if ( commentsEnabled && queryOptions.getComment() != null ) {
|
||||
sql = prependComment( sql, queryOptions.getComment() );
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
@ -3296,7 +3299,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
* Note that {@link SessionFactoryOptions#getCustomSqmTranslatorFactory()} has higher
|
||||
* precedence as it comes directly from the user config
|
||||
*
|
||||
* @see org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator
|
||||
* @see org.hibernate.query.sqm.sql.internal.StandardSqmTranslator
|
||||
* @see QueryEngine#getSqmTranslatorFactory()
|
||||
*/
|
||||
public SqmTranslatorFactory getSqmTranslatorFactory() {
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.engine.jdbc.Size;
|
|||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
|
@ -38,6 +39,11 @@ import org.hibernate.query.sqm.mutation.internal.idtable.GlobalTemporaryTableStr
|
|||
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorFirebirdDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceNameExtractorImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
|
@ -196,6 +202,17 @@ public class FirebirdDialect extends Dialect {
|
|||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new FirebirdSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Firebird 2.5 doesn't have a real {@link java.sql.Types#BOOLEAN}
|
||||
* type, so...
|
||||
|
@ -289,11 +306,6 @@ public class FirebirdDialect extends Dialect {
|
|||
return "add";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNoColumnsInsertString() {
|
||||
return "default values";
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Firebird.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class FirebirdSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public FirebirdSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
// Percent fetches or ties fetches aren't supported in Firebird
|
||||
// Before 3.0 there was also no support for window functions
|
||||
// Check if current query part is already row numbering to avoid infinite recursion
|
||||
return useOffsetFetchClause( queryPart ) && getQueryPartForRowNumbering() != queryPart
|
||||
&& getDialect().getVersion() >= 300 && !isRowsOnlyFetchClauseType( queryPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQueryGroup(QueryGroup queryGroup) {
|
||||
if ( shouldEmulateFetchClause( queryGroup ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( queryGroup, true );
|
||||
}
|
||||
else {
|
||||
super.visitQueryGroup( queryGroup );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQuerySpec(QuerySpec querySpec) {
|
||||
if ( shouldEmulateFetchClause( querySpec ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( querySpec, true );
|
||||
}
|
||||
else {
|
||||
super.visitQuerySpec( querySpec );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSelectClause(SelectClause selectClause) {
|
||||
Stack<Clause> clauseStack = getClauseStack();
|
||||
clauseStack.push( Clause.SELECT );
|
||||
|
||||
try {
|
||||
appendSql( "select " );
|
||||
visitSqlSelections( selectClause );
|
||||
}
|
||||
finally {
|
||||
clauseStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitSqlSelections(SelectClause selectClause) {
|
||||
if ( !supportsOffsetFetchClause() ) {
|
||||
renderFirstSkipClause( (QuerySpec) getQueryPartStack().getCurrent() );
|
||||
}
|
||||
if ( selectClause.isDistinct() ) {
|
||||
appendSql( "distinct " );
|
||||
}
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( supportsOffsetFetchClause() ) {
|
||||
// Firebird only supports a FIRST and SKIP clause before 3.0 which is handled in visitSqlSelections
|
||||
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||
renderOffsetFetchClause( queryPart, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Firebird does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Firebird does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
return getDialect().getVersion() >= 300;
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import java.sql.Types;
|
|||
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.NullOrdering;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
@ -23,6 +24,7 @@ import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
|
|||
import org.hibernate.dialect.sequence.H2SequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
|
@ -38,6 +40,11 @@ import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
|
|||
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2DatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
||||
|
@ -72,31 +79,35 @@ public class H2Dialect extends Dialect {
|
|||
}
|
||||
|
||||
public H2Dialect(int version, int buildId) {
|
||||
this(version + buildId);
|
||||
}
|
||||
|
||||
public H2Dialect(int version) {
|
||||
super();
|
||||
this.version = version;
|
||||
//TODO: actually I think all builds of 1.4 support OFFSET FETCH
|
||||
limitHandler = version > 140 || version == 140 && buildId >= 199
|
||||
// https://github.com/h2database/h2database/commit/b2cdf84e0b84eb8a482fa7dccdccc1ab95241440
|
||||
limitHandler = version >= 104195
|
||||
? OffsetFetchLimitHandler.INSTANCE
|
||||
: LimitOffsetLimitHandler.INSTANCE;
|
||||
|
||||
//Note: H2 'bit' is a synonym for 'boolean', not a proper bit type
|
||||
// registerColumnType( Types.BIT, "bit" );
|
||||
final int majorVersion = version / 100;
|
||||
final int minorVersion = version % 100 / 10;
|
||||
if ( version < 120 || version == 120 && buildId < 139 ) {
|
||||
|
||||
if ( version < 102139 ) {
|
||||
final int majorVersion = version / 100000;
|
||||
final int minorVersion = version % 100000 / 1000;
|
||||
final int buildId = version % 1000;
|
||||
LOG.unsupportedMultiTableBulkHqlJpaql( majorVersion, minorVersion, buildId );
|
||||
}
|
||||
supportsTuplesInSubqueries = majorVersion > 1 || minorVersion > 4 || buildId >= 198;
|
||||
supportsTuplesInSubqueries = version >= 104198;
|
||||
// Prior to 1.4.200 the 'cascade' in 'drop table' was implicit
|
||||
cascadeConstraints = version > 140 || version == 140 && buildId >= 200;
|
||||
cascadeConstraints = version >= 104200;
|
||||
|
||||
getDefaultProperties().setProperty( AvailableSettings.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
|
||||
// http://code.google.com/p/h2database/issues/detail?id=235
|
||||
getDefaultProperties().setProperty( AvailableSettings.NON_CONTEXTUAL_LOB_CREATION, "true" );
|
||||
|
||||
if ( buildId >= 32 ) {
|
||||
this.sequenceInformationExtractor = buildId >= 201
|
||||
if ( version >= 104032 ) {
|
||||
this.sequenceInformationExtractor = version >= 104201
|
||||
? SequenceInformationExtractorLegacyImpl.INSTANCE
|
||||
: SequenceInformationExtractorH2DatabaseImpl.INSTANCE;
|
||||
this.querySequenceString = "select * from INFORMATION_SCHEMA.SEQUENCES";
|
||||
|
@ -115,8 +126,8 @@ public class H2Dialect extends Dialect {
|
|||
|
||||
public H2Dialect(DialectResolutionInfo info) {
|
||||
this(
|
||||
info.getDatabaseMajorVersion()*100
|
||||
+ info.getDatabaseMinorVersion()*10,
|
||||
info.getDatabaseMajorVersion() * 100000
|
||||
+ info.getDatabaseMinorVersion() * 1000,
|
||||
parseBuildId( info )
|
||||
);
|
||||
}
|
||||
|
@ -174,6 +185,17 @@ public class H2Dialect extends Dialect {
|
|||
CommonFunctionFactory.rownum( queryEngine );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new H2SqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* In H2, the extract() function does not return
|
||||
* fractional seconds for the the field
|
||||
|
@ -269,6 +291,11 @@ public class H2Dialect extends Dialect {
|
|||
return "from dual";
|
||||
}
|
||||
|
||||
@Override
|
||||
public NullOrdering getNullOrdering() {
|
||||
return NullOrdering.FIRST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
|
||||
EntityMappingType entityDescriptor,
|
||||
|
@ -342,11 +369,6 @@ public class H2Dialect extends Dialect {
|
|||
return "call current_timestamp()";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for H2.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class H2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public H2SqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( isRowsOnlyFetchClauseType( queryPart ) ) {
|
||||
if ( supportsOffsetFetchClause() ) {
|
||||
renderOffsetFetchClause( queryPart, true );
|
||||
}
|
||||
else {
|
||||
renderLimitOffsetClause( queryPart );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( supportsOffsetFetchClausePercentWithTies() ) {
|
||||
renderOffsetFetchClause( queryPart, true );
|
||||
}
|
||||
else {
|
||||
// FETCH PERCENT and WITH TIES were introduced along with window functions
|
||||
throw new IllegalArgumentException( "Can't emulate fetch clause type: " + queryPart.getFetchClauseType() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// H2 does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// H2 does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
return getDialect().getVersion() >= 104195;
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClausePercentWithTies() {
|
||||
// Introduction of TIES clause https://github.com/h2database/h2database/commit/876e9fbe7baf11d01675bfe871aac2cf1b6104ce
|
||||
// Introduction of PERCENT support https://github.com/h2database/h2database/commit/f45913302e5f6ad149155a73763c0c59d8205849
|
||||
return getDialect().getVersion() >= 104198;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for HANA.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class HANASqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public HANASqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
// HANA only supports the LIMIT + OFFSET syntax but also window functions
|
||||
// Check if current query part is already row numbering to avoid infinite recursion
|
||||
return useOffsetFetchClause( queryPart ) && getQueryPartForRowNumbering() != queryPart
|
||||
&& !isRowsOnlyFetchClauseType( queryPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQueryGroup(QueryGroup queryGroup) {
|
||||
if ( shouldEmulateFetchClause( queryGroup ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( queryGroup, true );
|
||||
}
|
||||
else {
|
||||
super.visitQueryGroup( queryGroup );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQuerySpec(QuerySpec querySpec) {
|
||||
if ( shouldEmulateFetchClause( querySpec ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( querySpec, true );
|
||||
}
|
||||
else {
|
||||
super.visitQuerySpec( querySpec );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||
renderLimitOffsetClause( queryPart );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// HANA does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// HANA does not support this, but it can be emulated
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import javax.persistence.TemporalType;
|
|||
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.NullOrdering;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cfg.Environment;
|
||||
|
@ -34,6 +35,7 @@ import org.hibernate.dialect.sequence.HSQLSequenceSupport;
|
|||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
|
||||
|
@ -52,6 +54,11 @@ import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
|||
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorHSQLDBDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
|
||||
|
@ -205,6 +212,17 @@ public class HSQLDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new HSQLSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String castPattern(CastType from, CastType to) {
|
||||
if ( from== BOOLEAN
|
||||
|
@ -429,8 +447,8 @@ public class HSQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
public NullOrdering getNullOrdering() {
|
||||
return NullOrdering.FIRST;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for HSQL.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class HSQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public HSQLSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( supportsOffsetFetchClause() ) {
|
||||
assertRowsOnlyFetchClauseType( queryPart );
|
||||
renderOffsetFetchClause( queryPart, true );
|
||||
}
|
||||
else {
|
||||
renderLimitOffsetClause( queryPart );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// HSQL does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// HSQL does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
return getDialect().getVersion() >= 250;
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ import org.hibernate.dialect.sequence.SequenceSupport;
|
|||
import org.hibernate.dialect.unique.InformixUniqueDelegate;
|
||||
import org.hibernate.dialect.unique.UniqueDelegate;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
|
@ -30,6 +31,11 @@ import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
|||
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorInformixDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
@ -159,6 +165,17 @@ public class InformixDialect extends Dialect {
|
|||
//coalesce() and nullif() both supported since Informix 12
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new InformixSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Informix has no extract() function, but we can
|
||||
* partially emulate it by using the appropriate
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Informix.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class InformixSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public InformixSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitSqlSelections(SelectClause selectClause) {
|
||||
if ( supportsSkipFirstClause() ) {
|
||||
renderSkipFirstClause( (QuerySpec) getQueryPartStack().getCurrent() );
|
||||
}
|
||||
else {
|
||||
renderFirstClause( (QuerySpec) getQueryPartStack().getCurrent() );
|
||||
}
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return !supportsSkipFirstClause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchPlusOffsetExpression(
|
||||
Expression fetchClauseExpression,
|
||||
Expression offsetClauseExpression,
|
||||
int offset) {
|
||||
renderFetchPlusOffsetExpressionAsSingleParameter( fetchClauseExpression, offsetClauseExpression, offset );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchExpression(Expression fetchExpression) {
|
||||
if ( supportsParameterOffsetFetchExpression() ) {
|
||||
super.renderFetchExpression( fetchExpression );
|
||||
}
|
||||
else {
|
||||
renderExpressionAsLiteral( fetchExpression, getJdbcParameterBindings() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderOffsetExpression(Expression offsetExpression) {
|
||||
if ( supportsParameterOffsetFetchExpression() ) {
|
||||
super.renderOffsetExpression( offsetExpression );
|
||||
}
|
||||
else {
|
||||
renderExpressionAsLiteral( offsetExpression, getJdbcParameterBindings() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
// Informix only supports the SKIP clause in the top level query
|
||||
if ( !queryPart.isRoot() && queryPart.getOffsetClauseExpression() != null ) {
|
||||
throw new IllegalArgumentException( "Can't emulate offset clause in subquery" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Informix does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Informix does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
private boolean supportsParameterOffsetFetchExpression() {
|
||||
return getDialect().getVersion() >= 11;
|
||||
}
|
||||
|
||||
private boolean supportsSkipFirstClause() {
|
||||
return getDialect().getVersion() >= 11;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ import org.hibernate.dialect.pagination.LimitHandler;
|
|||
import org.hibernate.dialect.sequence.ANSISequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
|
@ -26,6 +27,11 @@ import org.hibernate.query.sqm.mutation.internal.idtable.GlobalTemporaryTableStr
|
|||
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceNameExtractorImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
@ -223,6 +229,17 @@ public class IngresDialect extends Dialect {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new IngresSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
|
||||
return "timestampadd(?1, ?2, ?3)";
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Ingres.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class IngresSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public IngresSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchPlusOffsetExpression(
|
||||
Expression fetchClauseExpression,
|
||||
Expression offsetClauseExpression,
|
||||
int offset) {
|
||||
renderFetchPlusOffsetExpressionAsSingleParameter( fetchClauseExpression, offsetClauseExpression, offset );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitSqlSelections(SelectClause selectClause) {
|
||||
if ( !supportsOffsetFetchClause() ) {
|
||||
renderFirstClause( (QuerySpec) getQueryPartStack().getCurrent() );
|
||||
}
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchExpression(Expression fetchExpression) {
|
||||
if ( supportsParameterOffsetFetchExpression() ) {
|
||||
super.renderFetchExpression( fetchExpression );
|
||||
}
|
||||
else {
|
||||
renderExpressionAsLiteral( fetchExpression, getJdbcParameterBindings() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderOffsetExpression(Expression offsetExpression) {
|
||||
if ( supportsParameterOffsetFetchExpression() ) {
|
||||
super.renderOffsetExpression( offsetExpression );
|
||||
}
|
||||
else {
|
||||
renderExpressionAsLiteral( offsetExpression, getJdbcParameterBindings() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( supportsOffsetFetchClause() ) {
|
||||
renderOffsetFetchClause( queryPart, false );
|
||||
}
|
||||
else if ( !queryPart.isRoot() && queryPart.getOffsetClauseExpression() != null ) {
|
||||
throw new IllegalArgumentException( "Can't emulate offset clause in subquery" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Ingres does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Ingres does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return !supportsOffsetFetchClause();
|
||||
}
|
||||
|
||||
private boolean supportsParameterOffsetFetchExpression() {
|
||||
return getDialect().getVersion() >= 930;
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
return getDialect().getVersion() >= 930;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,11 +6,16 @@
|
|||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.dialect.sequence.ANSISequenceSupport;
|
||||
import org.hibernate.dialect.sequence.MariaDBSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorMariaDBDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
@ -25,39 +30,51 @@ public class MariaDBDialect extends MySQLDialect {
|
|||
|
||||
private final int version;
|
||||
|
||||
int getMariaVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public MariaDBDialect() {
|
||||
this(500);
|
||||
}
|
||||
|
||||
public MariaDBDialect(int version) {
|
||||
super(version < 530 ? 500 : 570);
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public MariaDBDialect(DialectResolutionInfo info) {
|
||||
this( info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10 );
|
||||
}
|
||||
|
||||
public MariaDBDialect(int version) {
|
||||
super( version < 530 ? 500 : 570 );
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
super.initializeFunctionRegistry(queryEngine);
|
||||
|
||||
if ( getMariaVersion() >= 1020 ) {
|
||||
if ( getVersion() >= 1020 ) {
|
||||
queryEngine.getSqmFunctionRegistry().registerNamed("json_valid", StandardBasicTypes.NUMERIC_BOOLEAN);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new MariaDBSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsColumnCheck() {
|
||||
return getMariaVersion() >= 1020;
|
||||
return getVersion() >= 1020;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,14 +84,14 @@ public class MariaDBDialect extends MySQLDialect {
|
|||
|
||||
@Override
|
||||
public boolean supportsIfExistsBeforeConstraintName() {
|
||||
return getMariaVersion() >= 1000;
|
||||
return getVersion() >= 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SequenceSupport getSequenceSupport() {
|
||||
return getMariaVersion() < 1030
|
||||
return getVersion() < 1030
|
||||
? super.getSequenceSupport()
|
||||
: ANSISequenceSupport.INSTANCE;
|
||||
: MariaDBSequenceSupport.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for MariaDB.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class MariaDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public MariaDBSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
// Check if current query part is already row numbering to avoid infinite recursion
|
||||
return useOffsetFetchClause( queryPart ) && getQueryPartForRowNumbering() != queryPart && supportsWindowFunctions() && !isRowsOnlyFetchClauseType( queryPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQueryGroup(QueryGroup queryGroup) {
|
||||
if ( shouldEmulateFetchClause( queryGroup ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( queryGroup, true );
|
||||
}
|
||||
else {
|
||||
super.visitQueryGroup( queryGroup );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQuerySpec(QuerySpec querySpec) {
|
||||
if ( shouldEmulateFetchClause( querySpec ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( querySpec, true );
|
||||
}
|
||||
else {
|
||||
super.visitQuerySpec( querySpec );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||
renderCombinedLimitClause( queryPart );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// MariaDB does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// MariaDB does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
private boolean supportsWindowFunctions() {
|
||||
return getDialect().getVersion() >= 1020;
|
||||
}
|
||||
}
|
|
@ -9,8 +9,11 @@ package org.hibernate.dialect;
|
|||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||
import org.hibernate.dialect.pagination.LimitHandler;
|
||||
import org.hibernate.dialect.pagination.LimitOffsetLimitHandler;
|
||||
import org.hibernate.dialect.sequence.MaxDBSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.query.TrimSpec;
|
||||
|
@ -18,6 +21,11 @@ import org.hibernate.query.spi.QueryEngine;
|
|||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.CaseFragment;
|
||||
import org.hibernate.sql.DecodeCaseFragment;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorSAPDBDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
@ -60,6 +68,11 @@ public class MaxDBDialect extends Dialect {
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LimitHandler getLimitHandler() {
|
||||
return LimitOffsetLimitHandler.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
super.initializeFunctionRegistry( queryEngine );
|
||||
|
@ -112,6 +125,17 @@ public class MaxDBDialect extends Dialect {
|
|||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new MaxDBSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String trimPattern(TrimSpec specification, char character) {
|
||||
return AbstractTransactSQLDialect.replaceLtrimRtrim(specification, character);
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for MaxDB.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class MaxDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public MaxDBSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
renderLimitOffsetClause( queryPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// MaxDB does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// MaxDB does not support this, but it can be emulated
|
||||
}
|
||||
}
|
|
@ -15,10 +15,16 @@ import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
|
|||
import org.hibernate.dialect.sequence.MimerSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.CastType;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorMimerSQLDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
|
||||
|
@ -107,6 +113,17 @@ public class MimerSQLDialect extends Dialect {
|
|||
CommonFunctionFactory.localtimeLocaltimestamp( queryEngine );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new MimerSQLSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Mimer does have a real {@link java.sql.Types#BOOLEAN}
|
||||
* type, but it doesn't know how to cast to it.
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for MimerSQL.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class MimerSQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public MimerSQLSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
assertRowsOnlyFetchClauseType( queryPart );
|
||||
renderOffsetFetchClause( queryPart, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// MimerSQL does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// MimerSQL does not support this, but it can be emulated
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.NullOrdering;
|
||||
import org.hibernate.NullPrecedence;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
|
@ -22,6 +23,7 @@ import org.hibernate.dialect.sequence.SequenceSupport;
|
|||
import org.hibernate.dialect.unique.MySQLUniqueDelegate;
|
||||
import org.hibernate.dialect.unique.UniqueDelegate;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
|
@ -39,6 +41,11 @@ import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
|||
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
|
@ -59,15 +66,15 @@ import static org.hibernate.query.CastType.BOOLEAN;
|
|||
public class MySQLDialect extends Dialect {
|
||||
|
||||
private final UniqueDelegate uniqueDelegate;
|
||||
private MySQLStorageEngine storageEngine;
|
||||
private int version;
|
||||
private final MySQLStorageEngine storageEngine;
|
||||
private final int version;
|
||||
|
||||
public MySQLDialect(DialectResolutionInfo info) {
|
||||
this( info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10 );
|
||||
}
|
||||
|
||||
public MySQLDialect() {
|
||||
this(400);
|
||||
this( 400 );
|
||||
}
|
||||
|
||||
public MySQLDialect(int version) {
|
||||
|
@ -95,7 +102,7 @@ public class MySQLDialect extends Dialect {
|
|||
|
||||
registerColumnType( Types.NUMERIC, "decimal($p,$s)" ); //it's just a synonym
|
||||
|
||||
if ( getVersion() < 570) {
|
||||
if ( getMySQLVersion() < 570) {
|
||||
registerColumnType( Types.TIMESTAMP, "datetime" );
|
||||
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp" );
|
||||
}
|
||||
|
@ -107,7 +114,7 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
// max length for VARCHAR changed in 5.0.3
|
||||
final int maxVarcharLen = getVersion() < 500 ? 255 : 65_535;
|
||||
final int maxVarcharLen = getMySQLVersion() < 500 ? 255 : 65_535;
|
||||
|
||||
registerColumnType( Types.VARCHAR, maxVarcharLen, "varchar($l)" );
|
||||
registerColumnType( Types.VARBINARY, maxVarcharLen, "varbinary($l)" );
|
||||
|
@ -144,7 +151,7 @@ public class MySQLDialect extends Dialect {
|
|||
registerColumnType( Types.NCLOB, maxLobLen, "text" );
|
||||
registerColumnType( Types.NCLOB, maxTinyLobLen, "tinytext" );
|
||||
|
||||
if ( getVersion() >= 570) {
|
||||
if ( getMySQLVersion() >= 570) {
|
||||
// MySQL 5.7 brings JSON native support with a dedicated datatype
|
||||
// https://dev.mysql.com/doc/refman/5.7/en/json.html
|
||||
registerColumnType(Types.JAVA_OBJECT, "json");
|
||||
|
@ -163,6 +170,10 @@ public class MySQLDialect extends Dialect {
|
|||
return version;
|
||||
}
|
||||
|
||||
public int getMySQLVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDefaultLobLength() {
|
||||
//max length for mediumblob or mediumtext
|
||||
|
@ -237,7 +248,7 @@ public class MySQLDialect extends Dialect {
|
|||
CommonFunctionFactory.format_dateFormat( queryEngine );
|
||||
CommonFunctionFactory.makedateMaketime( queryEngine );
|
||||
|
||||
if ( getVersion() < 570 ) {
|
||||
if ( getMySQLVersion() < 570 ) {
|
||||
CommonFunctionFactory.sysdateParens( queryEngine );
|
||||
}
|
||||
else {
|
||||
|
@ -247,6 +258,17 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new MySQLSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void time(QueryEngine queryEngine) {
|
||||
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "time" )
|
||||
.setExactArgumentCount( 1 )
|
||||
|
@ -266,7 +288,7 @@ public class MySQLDialect extends Dialect {
|
|||
*/
|
||||
@Override
|
||||
public String currentTimestamp() {
|
||||
return getVersion() < 570 ? super.currentTimestamp() : "current_timestamp(6)";
|
||||
return getMySQLVersion() < 570 ? super.currentTimestamp() : "current_timestamp(6)";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -367,12 +389,12 @@ public class MySQLDialect extends Dialect {
|
|||
*/
|
||||
@Override
|
||||
public boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return getVersion() >= 570;
|
||||
return getMySQLVersion() >= 570;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return getVersion() >= 500;
|
||||
return getMySQLVersion() >= 500;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -382,7 +404,7 @@ public class MySQLDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public String getQueryHintString(String query, String hints) {
|
||||
return getVersion() < 500
|
||||
return getMySQLVersion() < 500
|
||||
? super.getQueryHintString( query, hints )
|
||||
: IndexQueryHintHandler.INSTANCE.addQueryHints( query, hints );
|
||||
}
|
||||
|
@ -396,7 +418,7 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() {
|
||||
return getVersion() < 500 ? super.getViolatedConstraintNameExtractor() : EXTRACTOR;
|
||||
return getMySQLVersion() < 500 ? super.getViolatedConstraintNameExtractor() : EXTRACTOR;
|
||||
}
|
||||
|
||||
private static final ViolatedConstraintNameExtractor EXTRACTOR =
|
||||
|
@ -508,6 +530,11 @@ public class MySQLDialect extends Dialect {
|
|||
return " comment '" + comment + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public NullOrdering getNullOrdering() {
|
||||
return NullOrdering.SMALLEST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
|
||||
EntityMappingType rootEntityDescriptor,
|
||||
|
@ -723,7 +750,7 @@ public class MySQLDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public String getTableTypeString() {
|
||||
String engineKeyword = getVersion() < 500 ? "type" : "engine";
|
||||
String engineKeyword = getMySQLVersion() < 500 ? "type" : "engine";
|
||||
return storageEngine.getTableTypeString( engineKeyword );
|
||||
}
|
||||
|
||||
|
@ -738,7 +765,7 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
protected MySQLStorageEngine getDefaultMySQLStorageEngine() {
|
||||
return getVersion() < 550 ? MyISAMStorageEngine.INSTANCE : InnoDBStorageEngine.INSTANCE;
|
||||
return getMySQLVersion() < 550 ? MyISAMStorageEngine.INSTANCE : InnoDBStorageEngine.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -900,12 +927,12 @@ public class MySQLDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public boolean supportsSkipLocked() {
|
||||
return getVersion() >= 800;
|
||||
return getMySQLVersion() >= 800;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsNoWait() {
|
||||
return getVersion() >= 800;
|
||||
return getMySQLVersion() >= 800;
|
||||
}
|
||||
|
||||
public boolean supportsWait() {
|
||||
|
@ -914,11 +941,11 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
boolean supportsForShare() {
|
||||
return getVersion() >= 800;
|
||||
return getMySQLVersion() >= 800;
|
||||
}
|
||||
|
||||
boolean supportsAliasLocks() {
|
||||
return getVersion() >= 800;
|
||||
return getMySQLVersion() >= 800;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for MySQL.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class MySQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public MySQLSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
// Check if current query part is already row numbering to avoid infinite recursion
|
||||
return useOffsetFetchClause( queryPart ) && getQueryPartForRowNumbering() != queryPart
|
||||
&& supportsWindowFunctions() && !isRowsOnlyFetchClauseType( queryPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQueryGroup(QueryGroup queryGroup) {
|
||||
if ( shouldEmulateFetchClause( queryGroup ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( queryGroup, true );
|
||||
}
|
||||
else {
|
||||
super.visitQueryGroup( queryGroup );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQuerySpec(QuerySpec querySpec) {
|
||||
if ( shouldEmulateFetchClause( querySpec ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( querySpec, true );
|
||||
}
|
||||
else {
|
||||
super.visitQuerySpec( querySpec );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||
renderCombinedLimitClause( queryPart );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// MySQL does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// MySQL does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
private boolean supportsWindowFunctions() {
|
||||
return getDialect().getVersion() >= 802;
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import org.hibernate.dialect.sequence.SequenceSupport;
|
|||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.config.spi.StandardConverters;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
|
@ -46,6 +47,11 @@ import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
|||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.sql.*;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
@ -179,6 +185,17 @@ public class OracleDialect extends Dialect {
|
|||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new OracleSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String currentDate() {
|
||||
return getVersion() < 9 ? currentTimestamp() : "current_date";
|
||||
|
@ -783,11 +800,6 @@ public class OracleDialect extends Dialect {
|
|||
return (ResultSet) ps.getObject( 1 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCommentOn() {
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Oracle.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class OracleSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public OracleSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
// Check if current query part is already row numbering to avoid infinite recursion
|
||||
return getQueryPartForRowNumbering() != queryPart && !supportsOffsetFetchClause() && (
|
||||
queryPart.isRoot() && hasLimit() || queryPart.getFetchClauseExpression() != null || queryPart.getOffsetClauseExpression() != null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQueryGroup(QueryGroup queryGroup) {
|
||||
if ( shouldEmulateFetchClause( queryGroup ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( queryGroup, true );
|
||||
}
|
||||
else {
|
||||
super.visitQueryGroup( queryGroup );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQuerySpec(QuerySpec querySpec) {
|
||||
if ( shouldEmulateFetchClause( querySpec ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( querySpec, true );
|
||||
}
|
||||
else {
|
||||
super.visitQuerySpec( querySpec );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||
if ( supportsOffsetFetchClause() ) {
|
||||
renderOffsetFetchClause( queryPart, true );
|
||||
}
|
||||
else {
|
||||
assertRowsOnlyFetchClauseType( queryPart );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderRowNumber(SelectClause selectClause, QueryPart queryPart) {
|
||||
if ( supportsOffsetFetchClause() || selectClause.isDistinct() ) {
|
||||
super.renderRowNumber( selectClause, queryPart );
|
||||
}
|
||||
else {
|
||||
appendSql( "rownum" );
|
||||
}
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
return getDialect().getVersion() >= 12;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,7 +9,6 @@ package org.hibernate.dialect;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.boot.model.TypeContributions;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||
|
@ -21,6 +20,7 @@ import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
|
|||
import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
|
||||
|
@ -33,12 +33,14 @@ import org.hibernate.procedure.spi.CallableStatementSupport;
|
|||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||
import org.hibernate.query.sqm.mutation.internal.cte.CteStrategy;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
|
@ -460,11 +462,6 @@ public class PostgreSQLDialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround for postgres bug #1453
|
||||
* <p/>
|
||||
|
@ -505,26 +502,22 @@ public class PostgreSQLDialect extends Dialect {
|
|||
return String.valueOf( bool );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
|
||||
EntityMappingType rootEntityDescriptor,
|
||||
RuntimeModelCreationContext runtimeModelCreationContext) {
|
||||
return new LocalTemporaryTableStrategy(
|
||||
new IdTable( rootEntityDescriptor, base -> "HT_" + base, this ),
|
||||
() -> new TempIdTableExporter( true, this::getTypeName ) {
|
||||
@Override
|
||||
protected String getCreateCommand() {
|
||||
return "create temporary table";
|
||||
}
|
||||
return new CteStrategy( rootEntityDescriptor, runtimeModelCreationContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCreateOptions() {
|
||||
return "on commit drop";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN,
|
||||
TempTableDdlTransactionHandling.NONE,
|
||||
runtimeModelCreationContext.getSessionFactory()
|
||||
);
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new PostgreSQLSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.MutationStatement;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for PostgreSQL.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class PostgreSQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public PostgreSQLSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
// Check if current query part is already row numbering to avoid infinite recursion
|
||||
if ( getQueryPartForRowNumbering() == queryPart || isRowsOnlyFetchClauseType( queryPart ) ) {
|
||||
return false;
|
||||
}
|
||||
final FetchClauseType fetchClauseType = queryPart.getFetchClauseType();
|
||||
switch ( fetchClauseType ) {
|
||||
case PERCENT_ONLY:
|
||||
case PERCENT_WITH_TIES:
|
||||
return !supportsOffsetFetchClausePercent();
|
||||
case ROWS_WITH_TIES:
|
||||
return !supportsOffsetFetchClauseWithTies();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQueryGroup(QueryGroup queryGroup) {
|
||||
if ( shouldEmulateFetchClause( queryGroup ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( queryGroup, true );
|
||||
}
|
||||
else {
|
||||
super.visitQueryGroup( queryGroup );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQuerySpec(QuerySpec querySpec) {
|
||||
if ( shouldEmulateFetchClause( querySpec ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( querySpec, true );
|
||||
}
|
||||
else {
|
||||
super.visitQuerySpec( querySpec );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||
if ( supportsOffsetFetchClause() ) {
|
||||
renderOffsetFetchClause( queryPart, true );
|
||||
}
|
||||
else {
|
||||
renderLimitOffsetClause( queryPart );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// PostgreSQL does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// PostgreSQL does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
return getDialect().getVersion() >= 840;
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClauseWithTies() {
|
||||
return getDialect().getVersion() >= 1300;
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClausePercent() {
|
||||
// Currently, percent always has to be emulated
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.Limit;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Unisys 2200.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class RDBMSOS2200SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public RDBMSOS2200SqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( queryPart.isRoot() ) {
|
||||
if ( hasLimit() ) {
|
||||
prepareLimitOffsetParameters();
|
||||
renderFetch( getLimitParameter(), getOffsetParameter(), FetchClauseType.ROWS_ONLY );
|
||||
}
|
||||
else if ( queryPart.getFetchClauseExpression() != null ) {
|
||||
renderFetch( queryPart.getFetchClauseExpression(), queryPart.getOffsetClauseExpression(), queryPart.getFetchClauseType() );
|
||||
}
|
||||
}
|
||||
else if ( queryPart.getOffsetClauseExpression() != null ) {
|
||||
throw new IllegalArgumentException( "Can't emulate offset clause in subquery" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchPlusOffsetExpression(
|
||||
Expression fetchClauseExpression,
|
||||
Expression offsetClauseExpression,
|
||||
int offset) {
|
||||
renderFetchPlusOffsetExpressionAsSingleParameter( fetchClauseExpression, offsetClauseExpression, offset );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Unisys 2200 does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Unisys 2200 does not support this, but it can be emulated
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import org.hibernate.dialect.pagination.FetchLimitHandler;
|
|||
import org.hibernate.dialect.pagination.LimitHandler;
|
||||
import org.hibernate.dialect.sequence.RDMSSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
|
@ -20,6 +21,12 @@ import org.hibernate.query.TrimSpec;
|
|||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.sql.CaseFragment;
|
||||
import org.hibernate.sql.DecodeCaseFragment;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.sql.Types;
|
||||
|
@ -151,6 +158,17 @@ public class RDMSOS2200Dialect extends Dialect {
|
|||
CommonFunctionFactory.monthsBetween( queryEngine );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new RDBMSOS2200SqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFractionalSecondPrecisionInNanos() {
|
||||
return 1_000; //microseconds
|
||||
|
@ -290,12 +308,6 @@ public class RDMSOS2200Dialect extends Dialect {
|
|||
return FetchLimitHandler.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
// RDMS supports the UNION ALL clause.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFromDual() {
|
||||
return "from rdms.rdms_dummy where key_col = 1";
|
||||
|
|
|
@ -18,11 +18,17 @@ import org.hibernate.dialect.sequence.ANSISequenceSupport;
|
|||
import org.hibernate.dialect.sequence.NoSequenceSupport;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.sql.SmallIntTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
@ -175,6 +181,17 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new SQLServerSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String currentTimestamp() {
|
||||
return "sysdatetime()";
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
import org.hibernate.sql.ast.tree.select.SortSpecification;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for SQL Server.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class SQLServerSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public SQLServerSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
protected OffsetFetchClauseMode getOffsetFetchClauseMode(QueryPart queryPart) {
|
||||
final int version = getDialect().getVersion();
|
||||
final boolean hasLimit;
|
||||
final boolean hasOffset;
|
||||
if ( queryPart.isRoot() && hasLimit() ) {
|
||||
hasLimit = getLimit().getMaxRowsJpa() != Integer.MAX_VALUE;
|
||||
hasOffset = getLimit().getFirstRowJpa() != 0;
|
||||
}
|
||||
else {
|
||||
hasLimit = queryPart.getFetchClauseExpression() != null;
|
||||
hasOffset = queryPart.getOffsetClauseExpression() != null;
|
||||
}
|
||||
if ( version < 9 || !hasOffset ) {
|
||||
return hasLimit ? OffsetFetchClauseMode.TOP_ONLY : null;
|
||||
}
|
||||
else if ( version < 11 || !isRowsOnlyFetchClauseType( queryPart ) ) {
|
||||
return OffsetFetchClauseMode.EMULATED;
|
||||
}
|
||||
else {
|
||||
return OffsetFetchClauseMode.STANDARD;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||
// Check if current query part is already row numbering to avoid infinite recursion
|
||||
return getQueryPartForRowNumbering() != queryPart && getOffsetFetchClauseMode( queryPart ) == OffsetFetchClauseMode.EMULATED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQueryGroup(QueryGroup queryGroup) {
|
||||
if ( shouldEmulateFetchClause( queryGroup ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( queryGroup, !isRowsOnlyFetchClauseType( queryGroup ) );
|
||||
}
|
||||
else {
|
||||
super.visitQueryGroup( queryGroup );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQuerySpec(QuerySpec querySpec) {
|
||||
if ( shouldEmulateFetchClause( querySpec ) ) {
|
||||
emulateFetchOffsetWithWindowFunctions( querySpec, !isRowsOnlyFetchClauseType( querySpec ) );
|
||||
}
|
||||
else {
|
||||
super.visitQuerySpec( querySpec );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return getDialect().getVersion() < 9;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchPlusOffsetExpression(
|
||||
Expression fetchClauseExpression,
|
||||
Expression offsetClauseExpression,
|
||||
int offset) {
|
||||
renderFetchPlusOffsetExpressionAsSingleParameter( fetchClauseExpression, offsetClauseExpression, offset );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitSqlSelections(SelectClause selectClause) {
|
||||
final QuerySpec querySpec = (QuerySpec) getQueryPartStack().getCurrent();
|
||||
final OffsetFetchClauseMode offsetFetchClauseMode = getOffsetFetchClauseMode( querySpec );
|
||||
if ( offsetFetchClauseMode == OffsetFetchClauseMode.TOP_ONLY ) {
|
||||
renderTopClause( querySpec, true );
|
||||
}
|
||||
else if ( offsetFetchClauseMode == OffsetFetchClauseMode.EMULATED ) {
|
||||
renderTopClause( querySpec, isRowsOnlyFetchClauseType( querySpec ) );
|
||||
}
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderOrderBy(boolean addWhitespace, List<SortSpecification> sortSpecifications) {
|
||||
if ( sortSpecifications != null && !sortSpecifications.isEmpty() ) {
|
||||
super.renderOrderBy( addWhitespace, sortSpecifications );
|
||||
}
|
||||
else if ( getClauseStack().getCurrent() == Clause.OVER ) {
|
||||
if ( addWhitespace ) {
|
||||
appendSql( ' ' );
|
||||
}
|
||||
renderEmptyOrderBy();
|
||||
}
|
||||
}
|
||||
|
||||
protected void renderEmptyOrderBy() {
|
||||
// Always need an order by clause: https://blog.jooq.org/2014/05/13/sql-server-trick-circumvent-missing-order-by-clause/
|
||||
appendSql( "order by @@version" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||
if ( getDialect().getVersion() < 9 && !queryPart.isRoot() && queryPart.getOffsetClauseExpression() != null ) {
|
||||
throw new IllegalArgumentException( "Can't emulate offset clause in subquery" );
|
||||
}
|
||||
// Note that SQL Server is very strict i.e. it requires an order by clause for TOP or OFFSET
|
||||
final OffsetFetchClauseMode offsetFetchClauseMode = getOffsetFetchClauseMode( queryPart );
|
||||
if ( offsetFetchClauseMode == OffsetFetchClauseMode.STANDARD ) {
|
||||
if ( !queryPart.hasSortSpecifications() ) {
|
||||
appendSql( ' ' );
|
||||
renderEmptyOrderBy();
|
||||
}
|
||||
final Expression offsetExpression;
|
||||
final Expression fetchExpression;
|
||||
final FetchClauseType fetchClauseType;
|
||||
if ( queryPart.isRoot() && hasLimit() ) {
|
||||
prepareLimitOffsetParameters();
|
||||
offsetExpression = getOffsetParameter();
|
||||
fetchExpression = getLimitParameter();
|
||||
fetchClauseType = FetchClauseType.ROWS_ONLY;
|
||||
}
|
||||
else {
|
||||
offsetExpression = queryPart.getOffsetClauseExpression();
|
||||
fetchExpression = queryPart.getFetchClauseExpression();
|
||||
fetchClauseType = queryPart.getFetchClauseType();
|
||||
}
|
||||
if ( offsetExpression == null ) {
|
||||
appendSql( " offset 0 rows" );
|
||||
}
|
||||
else {
|
||||
renderOffset( offsetExpression, true );
|
||||
}
|
||||
|
||||
if ( fetchExpression != null ) {
|
||||
renderFetch( fetchExpression, null, fetchClauseType );
|
||||
}
|
||||
}
|
||||
else if ( offsetFetchClauseMode == OffsetFetchClauseMode.TOP_ONLY && !queryPart.hasSortSpecifications() ) {
|
||||
appendSql( ' ' );
|
||||
renderEmptyOrderBy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// SQL Server does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// SQL Server does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
enum OffsetFetchClauseMode {
|
||||
STANDARD,
|
||||
TOP_ONLY,
|
||||
EMULATED;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ import org.hibernate.dialect.pagination.LimitHandler;
|
|||
import org.hibernate.dialect.pagination.LimitOffsetLimitHandler;
|
||||
import org.hibernate.dialect.unique.UniqueDelegate;
|
||||
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.mapping.Column;
|
||||
|
@ -31,6 +32,11 @@ import org.hibernate.persister.entity.Lockable;
|
|||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.spi.Exporter;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
|
@ -377,6 +383,17 @@ public class SpannerDialect extends Dialect {
|
|||
.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new SpannerSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Exporter<Table> getTableExporter() {
|
||||
return this.spannerTableExporter;
|
||||
|
@ -404,11 +421,6 @@ public class SpannerDialect extends Dialect {
|
|||
return String.valueOf( bool );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String translateExtractField(TemporalUnit unit) {
|
||||
switch (unit) {
|
||||
|
@ -769,7 +781,7 @@ public class SpannerDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public LimitHandler getLimitHandler() {
|
||||
return new LimitOffsetLimitHandler();
|
||||
return LimitOffsetLimitHandler.INSTANCE;
|
||||
}
|
||||
|
||||
/* Type conversion and casting */
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Spanner.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class SpannerSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public SpannerSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
renderLimitOffsetClause( queryPart );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Spanner does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Spanner does not support this, but it can be emulated
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import org.hibernate.LockOptions;
|
|||
import org.hibernate.dialect.pagination.LimitHandler;
|
||||
import org.hibernate.dialect.pagination.TopLimitHandler;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
|
@ -18,6 +19,11 @@ import org.hibernate.query.TrimSpec;
|
|||
import org.hibernate.sql.ForUpdateFragment;
|
||||
import org.hibernate.sql.JoinFragment;
|
||||
import org.hibernate.sql.Sybase11JoinFragment;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.TinyIntTypeDescriptor;
|
||||
|
||||
|
@ -70,6 +76,17 @@ public class SybaseASEDialect extends SybaseDialect {
|
|||
registerSybaseKeywords();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new SybaseASESqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The Sybase ASE {@code BIT} type does not allow
|
||||
* null values, so we don't use it.
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Sybase ASE.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class SybaseASESqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public SybaseASESqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Sybase ASE does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Sybase ASE does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitSqlSelections(SelectClause selectClause) {
|
||||
if ( supportsTopClause() ) {
|
||||
renderTopClause( (QuerySpec) getQueryPartStack().getCurrent(), true );
|
||||
}
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchPlusOffsetExpression(
|
||||
Expression fetchClauseExpression,
|
||||
Expression offsetClauseExpression,
|
||||
int offset) {
|
||||
renderFetchPlusOffsetExpressionAsSingleParameter( fetchClauseExpression, offsetClauseExpression, offset );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
assertRowsOnlyFetchClauseType( queryPart );
|
||||
if ( !queryPart.isRoot() && queryPart.hasOffsetOrFetchClause() ) {
|
||||
if ( queryPart.getFetchClauseExpression() != null && !supportsTopClause() || queryPart.getOffsetClauseExpression() != null ) {
|
||||
throw new IllegalArgumentException( "Can't emulate offset fetch clause in subquery" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchExpression(Expression fetchExpression) {
|
||||
if ( supportsParameterOffsetFetchExpression() ) {
|
||||
super.renderFetchExpression( fetchExpression );
|
||||
}
|
||||
else {
|
||||
renderExpressionAsLiteral( fetchExpression, getJdbcParameterBindings() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderOffsetExpression(Expression offsetExpression) {
|
||||
if ( supportsParameterOffsetFetchExpression() ) {
|
||||
super.renderOffsetExpression( offsetExpression );
|
||||
}
|
||||
else {
|
||||
renderExpressionAsLiteral( offsetExpression, getJdbcParameterBindings() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsMaxRows() {
|
||||
return !supportsTopClause();
|
||||
}
|
||||
|
||||
private boolean supportsTopClause() {
|
||||
return getDialect().getVersion() >= 1250;
|
||||
}
|
||||
|
||||
private boolean supportsParameterOffsetFetchExpression() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,12 @@ import org.hibernate.dialect.identity.SybaseAnywhereIdentityColumnSupport;
|
|||
import org.hibernate.dialect.pagination.LimitHandler;
|
||||
import org.hibernate.dialect.pagination.TopLimitHandler;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.type.descriptor.sql.BitTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
|
@ -56,6 +62,17 @@ public class SybaseAnywhereDialect extends SybaseDialect {
|
|||
registerColumnType( Types.VARBINARY, "long binary)" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new SybaseAnywhereSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTimezoneTypes() {
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Sybase Anywhere.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class SybaseAnywhereSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public SybaseAnywhereSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return getDialect().getVersion() < 900;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchPlusOffsetExpression(
|
||||
Expression fetchClauseExpression,
|
||||
Expression offsetClauseExpression,
|
||||
int offset) {
|
||||
renderFetchPlusOffsetExpressionAsSingleParameter( fetchClauseExpression, offsetClauseExpression, offset );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitSqlSelections(SelectClause selectClause) {
|
||||
if ( getDialect().getVersion() < 900 ) {
|
||||
renderTopClause( (QuerySpec) getQueryPartStack().getCurrent(), true );
|
||||
}
|
||||
else {
|
||||
renderTopStartAtClause( (QuerySpec) getQueryPartStack().getCurrent() );
|
||||
}
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderTopClause(QuerySpec querySpec, boolean addOffset) {
|
||||
assertRowsOnlyFetchClauseType( querySpec );
|
||||
super.renderTopClause( querySpec, addOffset );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderTopStartAtClause(QuerySpec querySpec) {
|
||||
assertRowsOnlyFetchClauseType( querySpec );
|
||||
super.renderTopStartAtClause( querySpec );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
// Sybase Anywhere only supports the TOP clause
|
||||
if ( getDialect().getVersion() < 900 && !queryPart.isRoot()
|
||||
&& useOffsetFetchClause( queryPart ) && queryPart.getOffsetClauseExpression() != null ) {
|
||||
throw new IllegalArgumentException( "Can't emulate offset clause in subquery" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Sybase Anywhere does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Sybase Anywhere does not support this, but it can be emulated
|
||||
}
|
||||
}
|
|
@ -8,8 +8,14 @@ package org.hibernate.dialect;
|
|||
|
||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
@ -45,6 +51,17 @@ public class SybaseDialect extends AbstractTransactSQLDialect {
|
|||
registerColumnType( Types.BIGINT, "numeric(19,0)" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new SybaseSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return version;
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Sybase.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class SybaseSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public SybaseSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Sybase does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Sybase does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
assertRowsOnlyFetchClauseType( queryPart );
|
||||
if ( !queryPart.isRoot() && queryPart.getOffsetClauseExpression() != null ) {
|
||||
throw new IllegalArgumentException( "Can't emulate offset clause in subquery" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsMaxRows() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ import org.hibernate.dialect.pagination.LimitHandler;
|
|||
import org.hibernate.dialect.pagination.TopLimitHandler;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
|
||||
import org.hibernate.mapping.Column;
|
||||
|
@ -34,6 +35,11 @@ import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
|||
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.ForUpdateFragment;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.internal.StandardIndexExporter;
|
||||
import org.hibernate.tool.schema.spi.Exporter;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
@ -116,6 +122,17 @@ public class TeradataDialect extends Dialect {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new TeradataSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return version;
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for Teradata.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class TeradataSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public TeradataSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchPlusOffsetExpression(
|
||||
Expression fetchClauseExpression,
|
||||
Expression offsetClauseExpression,
|
||||
int offset) {
|
||||
renderFetchPlusOffsetExpressionAsSingleParameter( fetchClauseExpression, offsetClauseExpression, offset );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitSqlSelections(SelectClause selectClause) {
|
||||
renderTopClause( (QuerySpec) getQueryPartStack().getCurrent(), true );
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
// Teradata only supports the TOP clause
|
||||
if ( !queryPart.isRoot() && queryPart.getOffsetClauseExpression() != null ) {
|
||||
throw new IllegalArgumentException( "Can't emulate offset clause in subquery" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// Teradata does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Teradata does not support this, but it can be emulated
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import org.hibernate.dialect.pagination.LimitHandler;
|
|||
import org.hibernate.dialect.pagination.TimesTenLimitHandler;
|
||||
import org.hibernate.dialect.sequence.SequenceSupport;
|
||||
import org.hibernate.dialect.sequence.TimesTenSequenceSupport;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.entity.Lockable;
|
||||
|
@ -24,6 +25,11 @@ import org.hibernate.query.sqm.mutation.internal.idtable.GlobalTemporaryTableStr
|
|||
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorTimesTenDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
@ -129,6 +135,17 @@ public class TimesTenDialect extends Dialect {
|
|||
).setArgumentListSignature("(pattern, string[, start])");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||
return new StandardSqlAstTranslatorFactory() {
|
||||
@Override
|
||||
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
return new TimesTenSqlAstTranslator<>( sessionFactory, statement );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
|
||||
switch (unit) {
|
||||
|
@ -262,11 +279,6 @@ public class TimesTenDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnionAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCircularCascadeDeleteConstraints() {
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
/**
|
||||
* A SQL AST translator for TimesTen.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class TimesTenSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||
|
||||
public TimesTenSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||
super( sessionFactory, statement );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSearchClause(CteStatement cte) {
|
||||
// TimesTen does not support this, but it's just a hint anyway
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// TimesTen does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitSqlSelections(SelectClause selectClause) {
|
||||
renderRowsToClause( (QuerySpec) getQueryPartStack().getCurrent() );
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderFetchPlusOffsetExpression(
|
||||
Expression fetchClauseExpression,
|
||||
Expression offsetClauseExpression,
|
||||
int offset) {
|
||||
renderFetchPlusOffsetExpressionAsSingleParameter( fetchClauseExpression, offsetClauseExpression, offset );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
// TimesTen uses ROWS TO clause
|
||||
}
|
||||
}
|
|
@ -101,12 +101,14 @@ public final class TypeNames {
|
|||
* the default type name otherwise
|
||||
*/
|
||||
public String get(int typeCode, Long size, Integer precision, Integer scale) {
|
||||
final Map<Long, String> map = weighted.get( typeCode );
|
||||
if ( map != null && map.size() > 0 ) {
|
||||
// iterate entries ordered by capacity to find first fit
|
||||
for ( Map.Entry<Long, String> entry: map.entrySet() ) {
|
||||
if ( size <= entry.getKey() ) {
|
||||
return replace( entry.getValue(), size, precision, scale );
|
||||
if ( size != null ) {
|
||||
final Map<Long, String> map = weighted.get( typeCode );
|
||||
if ( map != null && map.size() > 0 ) {
|
||||
// iterate entries ordered by capacity to find first fit
|
||||
for ( Map.Entry<Long, String> entry : map.entrySet() ) {
|
||||
if ( size <= entry.getKey() ) {
|
||||
return replace( entry.getValue(), size, precision, scale );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.query.Limit;
|
||||
|
||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||
import static java.util.regex.Pattern.compile;
|
||||
|
@ -270,6 +271,143 @@ public abstract class AbstractLimitHandler implements LimitHandler {
|
|||
return convertToFirstRowValue( selection.getFirstRow() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processSql(String sql, Limit limit) {
|
||||
throw new UnsupportedOperationException( "Paged queries not supported by " + getClass().getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bindLimitParametersAtStartOfQuery(Limit limit, PreparedStatement statement, int index)
|
||||
throws SQLException {
|
||||
return bindLimitParametersFirst()
|
||||
? bindLimitParameters( limit, statement, index )
|
||||
: 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bindLimitParametersAtEndOfQuery(Limit limit, PreparedStatement statement, int index)
|
||||
throws SQLException {
|
||||
return !bindLimitParametersFirst()
|
||||
? bindLimitParameters( limit, statement, index )
|
||||
: 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxRows(Limit limit, PreparedStatement statement) throws SQLException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation of binding parameter values needed by the LIMIT clause.
|
||||
*
|
||||
* @param limit the limit.
|
||||
* @param statement Statement to which to bind limit parameter values.
|
||||
* @param index Index from which to start binding.
|
||||
* @return The number of parameter values bound.
|
||||
* @throws SQLException Indicates problems binding parameter values.
|
||||
*/
|
||||
protected final int bindLimitParameters(Limit limit, PreparedStatement statement, int index)
|
||||
throws SQLException {
|
||||
|
||||
if ( !supportsVariableLimit() ) {
|
||||
//never any parameters to bind
|
||||
return 0;
|
||||
}
|
||||
|
||||
final boolean hasMaxRows = hasMaxRows( limit );
|
||||
final boolean hasFirstRow = hasFirstRow( limit );
|
||||
|
||||
final boolean bindLimit
|
||||
= hasMaxRows && supportsLimit()
|
||||
|| forceLimitUsage();
|
||||
final boolean bindOffset
|
||||
= hasFirstRow && supportsOffset()
|
||||
|| hasFirstRow && hasMaxRows && supportsLimitOffset();
|
||||
|
||||
if ( !bindLimit && !bindOffset ) {
|
||||
//no parameters to bind this time
|
||||
return 0;
|
||||
}
|
||||
|
||||
final boolean reverse = bindLimitParametersInReverseOrder();
|
||||
|
||||
if ( bindOffset ) {
|
||||
statement.setInt(
|
||||
index + ( reverse || !bindLimit ? 1 : 0 ),
|
||||
getFirstRow( limit )
|
||||
);
|
||||
}
|
||||
if ( bindLimit ) {
|
||||
statement.setInt(
|
||||
index + ( reverse || !bindOffset ? 0 : 1 ),
|
||||
getMaxOrLimit( limit )
|
||||
);
|
||||
}
|
||||
|
||||
return bindOffset && bindLimit ? 2 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a max row limit indicated?
|
||||
*
|
||||
* @param limit The limit
|
||||
*
|
||||
* @return Whether a max row limit was indicated
|
||||
*/
|
||||
public static boolean hasMaxRows(Limit limit) {
|
||||
return limit != null
|
||||
&& limit.getMaxRows() != null
|
||||
&& limit.getMaxRows() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a first row limit indicated?
|
||||
*
|
||||
* @param limit The limit
|
||||
*
|
||||
* @return Whether a first row limit was indicated
|
||||
*/
|
||||
public static boolean hasFirstRow(Limit limit) {
|
||||
return limit != null
|
||||
&& limit.getFirstRow() != null
|
||||
&& limit.getFirstRow() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Some dialect-specific LIMIT clauses require the maximum last row number
|
||||
* (aka, first_row_number + total_row_count), while others require the maximum
|
||||
* returned row count (the total maximum number of rows to return).
|
||||
*
|
||||
* @param limit The limit
|
||||
*
|
||||
* @return The appropriate value to bind into the limit clause.
|
||||
*/
|
||||
protected final int getMaxOrLimit(Limit limit) {
|
||||
if ( limit == null || limit.getMaxRows() == null ) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
final int firstRow = getFirstRow( limit );
|
||||
final int maxRows = limit.getMaxRows();
|
||||
final int maxOrLimit = useMaxForLimit()
|
||||
? maxRows + firstRow //TODO: maxRows + firstRow - 1, surely?
|
||||
: maxRows;
|
||||
// Use Integer.MAX_VALUE on overflow
|
||||
return maxOrLimit < 0 ? Integer.MAX_VALUE : maxOrLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the indicated first row for pagination
|
||||
*
|
||||
* @param limit The limit
|
||||
*
|
||||
* @return The first row
|
||||
*/
|
||||
protected final int getFirstRow(Limit limit) {
|
||||
if ( limit == null || limit.getFirstRow() == null ) {
|
||||
return 0;
|
||||
}
|
||||
return convertToFirstRowValue( limit.getFirstRow() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a fragment of SQL right after
|
||||
* {@code SELECT}, but before {@code DISTINCT}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.dialect.pagination;
|
||||
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.query.Limit;
|
||||
|
||||
import static java.lang.String.valueOf;
|
||||
|
||||
|
@ -34,13 +35,26 @@ public abstract class AbstractNoOffsetLimitHandler extends AbstractLimitHandler
|
|||
|
||||
@Override
|
||||
public String processSql(String sql, RowSelection selection) {
|
||||
if ( !hasMaxRows( selection) ) {
|
||||
if ( !hasMaxRows( selection ) ) {
|
||||
return sql;
|
||||
}
|
||||
String limitClause = limitClause();
|
||||
if ( !supportsVariableLimit() ) {
|
||||
String limit = valueOf( getMaxOrLimit(selection) );
|
||||
limitClause = limitClause.replace( "?", limit );
|
||||
String limitLiteral = valueOf( getMaxOrLimit(selection) );
|
||||
limitClause = limitClause.replace( "?", limitLiteral );
|
||||
}
|
||||
return insert( limitClause, sql );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processSql(String sql, Limit limit) {
|
||||
if ( !hasMaxRows( limit ) ) {
|
||||
return sql;
|
||||
}
|
||||
String limitClause = limitClause();
|
||||
if ( !supportsVariableLimit() ) {
|
||||
String limitLiteral = valueOf( getMaxOrLimit( limit ) );
|
||||
limitClause = limitClause.replace( "?", limitLiteral );
|
||||
}
|
||||
return insert( limitClause, sql );
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.dialect.pagination;
|
||||
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.query.Limit;
|
||||
|
||||
/**
|
||||
* Superclass for simple {@link LimitHandler}s that don't
|
||||
|
@ -20,10 +21,18 @@ public abstract class AbstractSimpleLimitHandler extends AbstractLimitHandler {
|
|||
|
||||
@Override
|
||||
public String processSql(String sql, RowSelection selection) {
|
||||
if ( !hasMaxRows( selection) ) {
|
||||
if ( !hasMaxRows( selection ) ) {
|
||||
return sql;
|
||||
}
|
||||
return insert( limitClause( hasFirstRow(selection) ), sql );
|
||||
return insert( limitClause( hasFirstRow( selection ) ), sql );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processSql(String sql, Limit limit) {
|
||||
if ( !hasMaxRows( limit ) ) {
|
||||
return sql;
|
||||
}
|
||||
return insert( limitClause( hasFirstRow( limit ) ), sql );
|
||||
}
|
||||
|
||||
protected String insert(String limitClause, String sql) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.dialect.pagination;
|
||||
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.query.Limit;
|
||||
|
||||
/**
|
||||
* A {@link LimitHandler} for DB2. Uses {@code FETCH FIRST n ROWS ONLY},
|
||||
|
@ -30,12 +31,33 @@ public class LegacyDB2LimitHandler extends AbstractLimitHandler {
|
|||
else {
|
||||
//on DB2, offset/fetch comes after all the
|
||||
//various "for update"ish clauses
|
||||
return insertAtEnd( fetchFirstRows(selection), sql );
|
||||
return insertAtEnd( fetchFirstRows( selection ), sql );
|
||||
}
|
||||
}
|
||||
|
||||
private String fetchFirstRows(RowSelection selection) {
|
||||
return " fetch first " + getMaxOrLimit( selection ) + " rows only";
|
||||
private String fetchFirstRows(RowSelection limit) {
|
||||
return " fetch first " + getMaxOrLimit( limit ) + " rows only";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processSql(String sql, Limit limit) {
|
||||
if ( hasFirstRow( limit ) ) {
|
||||
//nest the main query in an outer select
|
||||
return "select * from ( select row_.*, rownumber() over(order by order of row_) as rownumber_ from ( "
|
||||
+ sql + fetchFirstRows( limit )
|
||||
+ " ) as row_ ) as query_ where rownumber_ > "
|
||||
+ limit.getFirstRow()
|
||||
+ " order by rownumber_";
|
||||
}
|
||||
else {
|
||||
//on DB2, offset/fetch comes after all the
|
||||
//various "for update"ish clauses
|
||||
return insertAtEnd( fetchFirstRows( limit ), sql );
|
||||
}
|
||||
}
|
||||
|
||||
private String fetchFirstRows(Limit limit) {
|
||||
return " fetch first " + getMaxOrLimit( limit ) + " rows only";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.dialect.pagination;
|
|||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.query.Limit;
|
||||
|
||||
/**
|
||||
* Stub {@link LimitHandler} that delegates all operations
|
||||
|
@ -81,4 +82,20 @@ public class LegacyLimitHandler extends AbstractLimitHandler {
|
|||
getMaxOrLimit( selection )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processSql(String sql, Limit limit) {
|
||||
final boolean useLimitOffset
|
||||
= supportsOffset()
|
||||
&& hasFirstRow( limit )
|
||||
|| supportsLimit()
|
||||
&& supportsLimitOffset()
|
||||
&& hasFirstRow( limit )
|
||||
&& hasMaxRows( limit );
|
||||
return dialect.getLimitString(
|
||||
sql,
|
||||
useLimitOffset ? getFirstRow( limit ) : 0,
|
||||
getMaxOrLimit( limit )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.dialect.pagination;
|
||||
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.query.Limit;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
|
@ -56,6 +57,41 @@ public class LegacyOracleLimitHandler extends AbstractLimitHandler {
|
|||
return pagingSelect.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processSql(String sql, Limit limit) {
|
||||
final boolean hasOffset = hasFirstRow( limit );
|
||||
sql = sql.trim();
|
||||
|
||||
String forUpdateClause = null;
|
||||
Matcher forUpdateMatcher = getForUpdatePattern().matcher( sql );
|
||||
if ( forUpdateMatcher.find() ) {
|
||||
int forUpdateIndex = forUpdateMatcher.start();
|
||||
// save 'for update ...' and then remove it
|
||||
forUpdateClause = sql.substring( forUpdateIndex );
|
||||
sql = sql.substring( 0, forUpdateIndex );
|
||||
}
|
||||
|
||||
final StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 );
|
||||
if ( hasOffset ) {
|
||||
pagingSelect.append( "select * from (select row_.*, rownum rownum_ from (" ).append( sql );
|
||||
if ( version < 9 ) {
|
||||
pagingSelect.append( ") row_) where rownum_ <= ? and rownum_ > ?" );
|
||||
}
|
||||
else {
|
||||
pagingSelect.append( ") row_ where rownum <= ?) where rownum_ > ?" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
pagingSelect.append( "select * from (" ).append( sql ).append( ") where rownum <= ?" );
|
||||
}
|
||||
|
||||
if ( forUpdateClause != null ) {
|
||||
pagingSelect.append( forUpdateClause );
|
||||
}
|
||||
|
||||
return pagingSelect.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsLimit() {
|
||||
return true;
|
||||
|
|
|
@ -10,6 +10,8 @@ import java.sql.PreparedStatement;
|
|||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.query.Limit;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
|
||||
/**
|
||||
* Contract defining dialect-specific limit and offset handling.
|
||||
|
@ -40,6 +42,58 @@ public interface LimitHandler {
|
|||
*/
|
||||
boolean supportsLimitOffset();
|
||||
|
||||
default String processSql(String sql, Limit limit) {
|
||||
return processSql(
|
||||
sql,
|
||||
limit == null ? null : new RowSelection(
|
||||
limit.getFirstRow(),
|
||||
limit.getMaxRows(),
|
||||
null,
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
default int bindLimitParametersAtStartOfQuery(Limit limit, PreparedStatement statement, int index)
|
||||
throws SQLException {
|
||||
return bindLimitParametersAtStartOfQuery(
|
||||
limit == null ? null : new RowSelection(
|
||||
limit.getFirstRow(),
|
||||
limit.getMaxRows(),
|
||||
null,
|
||||
null
|
||||
),
|
||||
statement,
|
||||
index
|
||||
);
|
||||
}
|
||||
|
||||
default int bindLimitParametersAtEndOfQuery(Limit limit, PreparedStatement statement, int index)
|
||||
throws SQLException {
|
||||
return bindLimitParametersAtEndOfQuery(
|
||||
limit == null ? null : new RowSelection(
|
||||
limit.getFirstRow(),
|
||||
limit.getMaxRows(),
|
||||
null,
|
||||
null
|
||||
),
|
||||
statement,
|
||||
index
|
||||
);
|
||||
}
|
||||
|
||||
default void setMaxRows(Limit limit, PreparedStatement statement) throws SQLException {
|
||||
setMaxRows(
|
||||
limit == null ? null : new RowSelection(
|
||||
limit.getFirstRow(),
|
||||
limit.getMaxRows(),
|
||||
null,
|
||||
null
|
||||
),
|
||||
statement
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return processed SQL query.
|
||||
*
|
||||
|
@ -47,7 +101,9 @@ public interface LimitHandler {
|
|||
* @param selection the selection criteria for rows.
|
||||
*
|
||||
* @return Query statement with LIMIT clause applied.
|
||||
* @deprecated todo (6.0): remove in favor of Limit version?
|
||||
*/
|
||||
@Deprecated
|
||||
String processSql(String sql, RowSelection selection);
|
||||
|
||||
/**
|
||||
|
@ -60,7 +116,9 @@ public interface LimitHandler {
|
|||
* @param index Index from which to start binding.
|
||||
* @return The number of parameter values bound.
|
||||
* @throws SQLException Indicates problems binding parameter values.
|
||||
* @deprecated todo (6.0): remove in favor of Limit version?
|
||||
*/
|
||||
@Deprecated
|
||||
int bindLimitParametersAtStartOfQuery(RowSelection selection, PreparedStatement statement, int index)
|
||||
throws SQLException;
|
||||
|
||||
|
@ -74,7 +132,9 @@ public interface LimitHandler {
|
|||
* @param index Index from which to start binding.
|
||||
* @return The number of parameter values bound.
|
||||
* @throws SQLException Indicates problems binding parameter values.
|
||||
* @deprecated todo (6.0): remove in favor of Limit version?
|
||||
*/
|
||||
@Deprecated
|
||||
int bindLimitParametersAtEndOfQuery(RowSelection selection, PreparedStatement statement, int index)
|
||||
throws SQLException;
|
||||
|
||||
|
@ -86,6 +146,8 @@ public interface LimitHandler {
|
|||
* @param selection the selection criteria for rows.
|
||||
* @param statement Statement which number of returned rows shall be limited.
|
||||
* @throws SQLException Indicates problems while limiting maximum rows returned.
|
||||
* @deprecated todo (6.0): remove in favor of Limit version?
|
||||
*/
|
||||
@Deprecated
|
||||
void setMaxRows(RowSelection selection, PreparedStatement statement) throws SQLException;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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.dialect.pagination;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.query.Limit;
|
||||
|
||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||
import static java.util.regex.Pattern.compile;
|
||||
|
||||
/**
|
||||
* Handler not supporting query LIMIT clause. JDBC API is used to set maximum number of returned rows.
|
||||
*
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public class NoopLimitHandler extends AbstractLimitHandler {
|
||||
|
||||
public static final NoopLimitHandler INSTANCE = new NoopLimitHandler();
|
||||
|
||||
@Override
|
||||
public String processSql(String sql, RowSelection selection) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bindLimitParametersAtStartOfQuery(RowSelection selection, PreparedStatement statement, int index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bindLimitParametersAtEndOfQuery(RowSelection selection, PreparedStatement statement, int index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxRows(RowSelection selection, PreparedStatement statement) throws SQLException {
|
||||
if ( selection != null && selection.getMaxRows() != null && selection.getMaxRows() > 0 ) {
|
||||
final int maxRows = selection.getMaxRows() + convertToFirstRowValue(
|
||||
selection.getFirstRow() == null ? 0 : selection.getFirstRow()
|
||||
);
|
||||
// Use Integer.MAX_VALUE on overflow
|
||||
if ( maxRows < 0 ) {
|
||||
statement.setMaxRows( Integer.MAX_VALUE );
|
||||
}
|
||||
else {
|
||||
statement.setMaxRows( maxRows );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processSql(String sql, Limit limit) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bindLimitParametersAtStartOfQuery(Limit limit, PreparedStatement statement, int index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bindLimitParametersAtEndOfQuery(Limit limit, PreparedStatement statement, int index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxRows(Limit limit, PreparedStatement statement) throws SQLException {
|
||||
if ( limit != null && limit.getMaxRows() != null && limit.getMaxRows() > 0 ) {
|
||||
final int maxRows = limit.getMaxRows() + convertToFirstRowValue(
|
||||
limit.getFirstRow() == null ? 0 : limit.getFirstRow()
|
||||
);
|
||||
// Use Integer.MAX_VALUE on overflow
|
||||
if ( maxRows < 0 ) {
|
||||
statement.setMaxRows( Integer.MAX_VALUE );
|
||||
}
|
||||
else {
|
||||
statement.setMaxRows( maxRows );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.dialect.pagination;
|
||||
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.query.Limit;
|
||||
|
||||
/**
|
||||
* A {@link LimitHandler} for databases which support the
|
||||
|
@ -71,6 +72,52 @@ public class OffsetFetchLimitHandler extends AbstractLimitHandler {
|
|||
return insert( offsetFetch.toString(), sql );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processSql(String sql, Limit limit) {
|
||||
|
||||
boolean hasFirstRow = hasFirstRow(limit);
|
||||
boolean hasMaxRows = hasMaxRows(limit);
|
||||
|
||||
if ( !hasFirstRow && !hasMaxRows ) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
StringBuilder offsetFetch = new StringBuilder();
|
||||
|
||||
begin(sql, offsetFetch, hasFirstRow, hasMaxRows);
|
||||
|
||||
if ( hasFirstRow ) {
|
||||
offsetFetch.append( " offset " );
|
||||
if ( supportsVariableLimit() ) {
|
||||
offsetFetch.append( "?" );
|
||||
}
|
||||
else {
|
||||
offsetFetch.append( limit.getFirstRow() );
|
||||
}
|
||||
if ( !isIngres() ) {
|
||||
offsetFetch.append( " rows" );
|
||||
}
|
||||
|
||||
}
|
||||
if ( hasMaxRows ) {
|
||||
if ( hasFirstRow ) {
|
||||
offsetFetch.append( " fetch next " );
|
||||
}
|
||||
else {
|
||||
offsetFetch.append( " fetch first " );
|
||||
}
|
||||
if ( supportsVariableLimit() ) {
|
||||
offsetFetch.append( "?" );
|
||||
}
|
||||
else {
|
||||
offsetFetch.append( getMaxOrLimit( limit ) );
|
||||
}
|
||||
offsetFetch.append( " rows only" );
|
||||
}
|
||||
|
||||
return insert( offsetFetch.toString(), sql );
|
||||
}
|
||||
|
||||
void begin(String sql, StringBuilder offsetFetch, boolean hasFirstRow, boolean hasMaxRows) {}
|
||||
|
||||
String insert(String offsetFetch, String sql) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.regex.Pattern;
|
|||
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.query.Limit;
|
||||
|
||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||
import static java.util.regex.Pattern.compile;
|
||||
|
@ -132,6 +133,84 @@ public class SQLServer2005LimitHandler extends AbstractLimitHandler {
|
|||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the offset of the given {@link RowSelection} is {@literal 0},
|
||||
* add a {@code top(?)} clause to the given SQL query. When the offset
|
||||
* is non-zero, wrap the given query in an outer query that limits the
|
||||
* results using the {@code row_number()} window function.
|
||||
*
|
||||
* <pre>
|
||||
* with query_ as (
|
||||
* select row_.*, row_number()
|
||||
* over (order by current_timestamp) AS rownumber_
|
||||
* from ( [original-query] ) row_
|
||||
* )
|
||||
* select [alias-list] from query_
|
||||
* where rownumber_ >= ? and rownumber_ < ?
|
||||
* </pre>
|
||||
*
|
||||
* Where {@code [original-query]} is the original SQL query, with a
|
||||
* {@code top()} clause added iff the query has an {@code order by}
|
||||
* clause, and with generated aliases added to any elements of the
|
||||
* projection list that don't already have aliases, and
|
||||
* {@code [alias-list]} is a list of aliases in the projection list.
|
||||
*
|
||||
* @return A new SQL statement
|
||||
*/
|
||||
@Override
|
||||
public String processSql(String sql, Limit limit) {
|
||||
sql = sql.trim();
|
||||
if ( sql.endsWith(";") ) {
|
||||
sql = sql.substring( 0, sql.length()-1 );
|
||||
}
|
||||
|
||||
final int selectOffset = Keyword.SELECT.rootOffset( sql );
|
||||
final int afterSelectOffset = Keyword.SELECT.endOffset( sql, selectOffset );
|
||||
final int fromOffset = Keyword.FROM.rootOffset( sql ); //TODO: what if there is no 'from' clause?!
|
||||
|
||||
boolean hasCommonTables = Keyword.WITH.occursAt( sql, 0 );
|
||||
boolean hasOrderBy = Keyword.ORDER_BY.rootOffset( sql ) > 0;
|
||||
boolean hasFirstRow = hasFirstRow( limit );
|
||||
|
||||
final StringBuilder result = new StringBuilder( sql );
|
||||
|
||||
if ( !hasFirstRow || hasOrderBy ) {
|
||||
result.insert( afterSelectOffset, " top(?)" );
|
||||
topAdded = true;
|
||||
}
|
||||
|
||||
if ( hasFirstRow ) {
|
||||
|
||||
// enclose original SQL statement with outer query
|
||||
// that provides the rownumber_ column
|
||||
|
||||
String aliases = selectAliases( sql, afterSelectOffset, fromOffset, result ); //warning: changes result by side-effect
|
||||
result.insert( selectOffset, ( hasCommonTables ? "," : "with" )
|
||||
+ " query_ as (select row_.*, row_number() over (order by current_timestamp) as rownumber_ from (" )
|
||||
.append( ") row_) select " ).append( aliases )
|
||||
.append( " from query_ where rownumber_ >= ? and rownumber_ < ?" );
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bindLimitParametersAtStartOfQuery(Limit limit, PreparedStatement statement, int index) throws SQLException {
|
||||
if ( topAdded ) {
|
||||
// bind parameter to top(?)
|
||||
statement.setInt( index, getMaxOrLimit( limit ) - 1 );
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bindLimitParametersAtEndOfQuery(Limit limit, PreparedStatement statement, int index) throws SQLException {
|
||||
return hasFirstRow( limit )
|
||||
? super.bindLimitParametersAtEndOfQuery( limit, statement, index )
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add any missing aliases to the given {@code select} list, and return
|
||||
* comma-separated list of all aliases in the list, unless the given list
|
||||
|
|
|
@ -52,7 +52,8 @@ public class SQLServer2012LimitHandler extends OffsetFetchLimitHandler {
|
|||
//if we can find the end of the select
|
||||
//clause, we will add a dummy column to
|
||||
//it below, so order by that column
|
||||
offsetFetch.append("zero_");
|
||||
// Always need an order by clause: https://blog.jooq.org/2014/05/13/sql-server-trick-circumvent-missing-order-by-clause/
|
||||
offsetFetch.append("@@version");
|
||||
}
|
||||
else {
|
||||
//otherwise order by the first column
|
||||
|
@ -66,22 +67,4 @@ public class SQLServer2012LimitHandler extends OffsetFetchLimitHandler {
|
|||
offsetFetch.append(" offset 0 rows");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String insert(String offsetFetch, String sql) {
|
||||
String result = super.insert( offsetFetch, sql );
|
||||
if ( Keyword.ORDER_BY.rootOffset( sql ) <= 0 ) {
|
||||
int from = Keyword.FROM.rootOffset( sql );
|
||||
if ( from > 0 ) {
|
||||
//insert the dummy column at the end of
|
||||
//the select list (don't add it at the
|
||||
//start, 'cos that would mess up reading
|
||||
//results by index)
|
||||
return new StringBuilder( result )
|
||||
.insert( from, ", 0 as zero_ " )
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.dialect.pagination;
|
||||
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.query.Limit;
|
||||
|
||||
/**
|
||||
* A {@link LimitHandler} for Informix which supports the syntax
|
||||
|
@ -56,6 +57,40 @@ public class SkipFirstLimitHandler extends AbstractLimitHandler {
|
|||
return insertAfterSelect( sql, skipFirst.toString() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processSql(String sql, Limit limit) {
|
||||
|
||||
boolean hasFirstRow = hasFirstRow( limit );
|
||||
boolean hasMaxRows = hasMaxRows( limit );
|
||||
|
||||
if ( !hasFirstRow && !hasMaxRows ) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
StringBuilder skipFirst = new StringBuilder();
|
||||
|
||||
if ( supportsVariableLimit() ) {
|
||||
if ( hasFirstRow ) {
|
||||
skipFirst.append( " skip ?" );
|
||||
}
|
||||
if ( hasMaxRows ) {
|
||||
skipFirst.append( " first ?" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( hasFirstRow ) {
|
||||
skipFirst.append( " skip " )
|
||||
.append( limit.getFirstRow() );
|
||||
}
|
||||
if ( hasMaxRows ) {
|
||||
skipFirst.append( " first " )
|
||||
.append( getMaxOrLimit( limit ) );
|
||||
}
|
||||
}
|
||||
|
||||
return insertAfterSelect( sql, skipFirst.toString() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean supportsLimit() {
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.dialect.sequence;
|
||||
|
||||
/**
|
||||
* Sequence support for {@link org.hibernate.dialect.MariaDBDialect}.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public final class MariaDBSequenceSupport extends ANSISequenceSupport {
|
||||
|
||||
public static final SequenceSupport INSTANCE = new MariaDBSequenceSupport();
|
||||
|
||||
@Override
|
||||
public boolean sometimesNeedsStartingValue() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -10,7 +10,9 @@ package org.hibernate.engine.spi;
|
|||
* Represents a selection criteria for rows in a JDBC {@link java.sql.ResultSet}
|
||||
*
|
||||
* @author Gavin King
|
||||
* @deprecated todo (6.0): remove in favor of Limit within QueryOptions?
|
||||
*/
|
||||
@Deprecated
|
||||
public final class RowSelection {
|
||||
private Integer firstRow;
|
||||
private Integer maxRows;
|
||||
|
|
|
@ -275,6 +275,18 @@ public final class CollectionHelper {
|
|||
return objects == null || objects.length == 0;
|
||||
}
|
||||
|
||||
public static <T> List<T> listOf(T value1) {
|
||||
final List<T> list = new ArrayList<>( 1 );
|
||||
list.add( value1 );
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> List<T> listOf(T... values) {
|
||||
final List<T> list = new ArrayList<>( values.length );
|
||||
Collections.addAll( list, values );
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> Set<T> setOf(T... values) {
|
||||
final HashSet<T> set = new HashSet<>( determineProperSizing( values.length ) );
|
||||
Collections.addAll( set, values );
|
||||
|
|
|
@ -99,11 +99,10 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
|
|||
sessionFactory
|
||||
);
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlSelect );
|
||||
|
||||
final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
|
||||
|
||||
applyNaturalIdAsJdbcParameters( bindValue, jdbcParameters, jdbcParamBindings, session );
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
|
||||
.translate( jdbcParamBindings, QueryOptions.NONE );
|
||||
|
||||
//noinspection unchecked
|
||||
final List<T> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
|
||||
|
@ -179,8 +178,6 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
|
|||
sessionFactory
|
||||
);
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlSelect );
|
||||
|
||||
final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
|
||||
applyNaturalIdAsJdbcParameters(
|
||||
bindValue,
|
||||
|
@ -188,6 +185,8 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
|
|||
jdbcParamBindings,
|
||||
session
|
||||
);
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
|
||||
.translate( jdbcParamBindings, QueryOptions.NONE );
|
||||
|
||||
final List<?> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
|
||||
jdbcSelect,
|
||||
|
@ -252,10 +251,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlSelect );
|
||||
|
||||
final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
|
||||
|
||||
int offset = jdbcParamBindings.registerParametersForEachJdbcValue(
|
||||
id,
|
||||
Clause.WHERE,
|
||||
|
@ -264,6 +260,8 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
|
|||
session
|
||||
);
|
||||
assert offset == jdbcParameters.size();
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
|
||||
.translate( jdbcParamBindings, QueryOptions.NONE );
|
||||
|
||||
final List<Object[]> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
|
||||
jdbcSelect,
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.loader.ast.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
|
@ -30,7 +29,6 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||
import org.hibernate.sql.exec.spi.Callback;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
|
@ -116,11 +114,7 @@ public class CollectionElementLoaderByIndex implements Loader {
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory )
|
||||
.translate( sqlAst );
|
||||
|
||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( keyJdbcCount );
|
||||
jdbcSelect.bindFilterJdbcParameters( jdbcParameterBindings );
|
||||
|
||||
int offset = jdbcParameterBindings.registerParametersForEachJdbcValue(
|
||||
key,
|
||||
|
@ -138,6 +132,8 @@ public class CollectionElementLoaderByIndex implements Loader {
|
|||
session
|
||||
);
|
||||
assert offset == jdbcParameters.size();
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
|
||||
.translate( jdbcParameterBindings, QueryOptions.NONE );
|
||||
|
||||
List<Object> list = jdbcServices.getJdbcSelectExecutor().list(
|
||||
jdbcSelect,
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.loader.ast.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
|
@ -27,7 +26,6 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||
import org.hibernate.sql.exec.spi.Callback;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
|
@ -159,7 +157,8 @@ public class CollectionLoaderBatchKey implements CollectionLoader {
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
|
||||
.translate( null, QueryOptions.NONE );
|
||||
|
||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( keyJdbcCount * smallBatchLength );
|
||||
jdbcSelect.bindFilterJdbcParameters( jdbcParameterBindings );
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.loader.ast.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
|
@ -26,7 +25,6 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||
import org.hibernate.sql.exec.spi.Callback;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
|
@ -95,11 +93,7 @@ public class CollectionLoaderSingleKey implements CollectionLoader {
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
|
||||
|
||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( keyJdbcCount );
|
||||
jdbcSelect.bindFilterJdbcParameters( jdbcParameterBindings );
|
||||
|
||||
int offset = jdbcParameterBindings.registerParametersForEachJdbcValue(
|
||||
key,
|
||||
Clause.WHERE,
|
||||
|
@ -108,6 +102,8 @@ public class CollectionLoaderSingleKey implements CollectionLoader {
|
|||
session
|
||||
);
|
||||
assert offset == jdbcParameters.size();
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
|
||||
.translate( jdbcParameterBindings, QueryOptions.NONE );
|
||||
|
||||
jdbcServices.getJdbcSelectExecutor().list(
|
||||
jdbcSelect,
|
||||
|
|
|
@ -68,7 +68,8 @@ public class CollectionLoaderSubSelectFetch implements CollectionLoader {
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
|
||||
.translate( subselect.getLoadingJdbcParameterBindings(), QueryOptions.NONE );
|
||||
|
||||
jdbcServices.getJdbcSelectExecutor().list(
|
||||
jdbcSelect,
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.loader.ast.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
|
@ -32,7 +31,6 @@ import org.hibernate.sql.ast.tree.from.TableReference;
|
|||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
|
||||
|
@ -185,7 +183,8 @@ class DatabaseSnapshotExecutor {
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( selectStatement );
|
||||
jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, selectStatement )
|
||||
.translate( null, QueryOptions.NONE );
|
||||
}
|
||||
|
||||
Object[] loadDatabaseSnapshot(Object id, SharedSessionContractImplementor session) {
|
||||
|
|
|
@ -64,6 +64,7 @@ import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
|||
import org.hibernate.sql.ast.tree.predicate.InListPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
|
||||
|
@ -882,7 +883,7 @@ public class LoaderSelectBuilder {
|
|||
);
|
||||
}
|
||||
|
||||
private QuerySpec generateSubSelect(
|
||||
private QueryPart generateSubSelect(
|
||||
PluralAttributeMapping attributeMapping,
|
||||
TableGroup rootTableGroup,
|
||||
SubselectFetch subselect,
|
||||
|
|
|
@ -25,7 +25,7 @@ import org.hibernate.query.NavigablePath;
|
|||
import org.hibernate.query.ResultListTransformer;
|
||||
import org.hibernate.query.TupleTransformer;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.query.sqm.sql.internal.SqlAstQuerySpecProcessingStateImpl;
|
||||
import org.hibernate.query.sqm.sql.internal.SqlAstQueryPartProcessingStateImpl;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||
|
@ -35,6 +35,7 @@ import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
|||
import org.hibernate.sql.ast.spi.SqlAstProcessingState;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
|
@ -49,11 +50,10 @@ public class LoaderSqlAstCreationState
|
|||
List<Fetch> visitFetches(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState);
|
||||
}
|
||||
|
||||
private final QuerySpec querySpec;
|
||||
private final SqlAliasBaseManager sqlAliasBaseManager;
|
||||
private final boolean forceIdentifierSelection;
|
||||
private final SqlAstCreationContext sf;
|
||||
private final SqlAstQuerySpecProcessingStateImpl processingState;
|
||||
private final SqlAstQueryPartProcessingStateImpl processingState;
|
||||
private final FromClauseAccess fromClauseAccess;
|
||||
private final LockOptions lockOptions;
|
||||
private final FetchProcessor fetchProcessor;
|
||||
|
@ -61,22 +61,21 @@ public class LoaderSqlAstCreationState
|
|||
private Set<AssociationKey> visitedAssociationKeys = new HashSet<>();
|
||||
|
||||
public LoaderSqlAstCreationState(
|
||||
QuerySpec querySpec,
|
||||
QueryPart queryPart,
|
||||
SqlAliasBaseManager sqlAliasBaseManager,
|
||||
FromClauseAccess fromClauseAccess,
|
||||
LockOptions lockOptions,
|
||||
FetchProcessor fetchProcessor,
|
||||
boolean forceIdentifierSelection,
|
||||
SqlAstCreationContext sf) {
|
||||
this.querySpec = querySpec;
|
||||
this.sqlAliasBaseManager = sqlAliasBaseManager;
|
||||
this.fromClauseAccess = fromClauseAccess;
|
||||
this.lockOptions = lockOptions;
|
||||
this.fetchProcessor = fetchProcessor;
|
||||
this.forceIdentifierSelection = forceIdentifierSelection;
|
||||
this.sf = sf;
|
||||
processingState = new SqlAstQuerySpecProcessingStateImpl(
|
||||
querySpec,
|
||||
this.processingState = new SqlAstQueryPartProcessingStateImpl(
|
||||
queryPart,
|
||||
this,
|
||||
this,
|
||||
() -> Clause.IRRELEVANT
|
||||
|
@ -99,10 +98,6 @@ public class LoaderSqlAstCreationState
|
|||
);
|
||||
}
|
||||
|
||||
public QuerySpec getQuerySpec() {
|
||||
return querySpec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstCreationContext getCreationContext() {
|
||||
return sf;
|
||||
|
@ -135,7 +130,7 @@ public class LoaderSqlAstCreationState
|
|||
|
||||
@Override
|
||||
public List<Fetch> visitFetches(FetchParent fetchParent) {
|
||||
return fetchProcessor.visitFetches( fetchParent, getQuerySpec(), this );
|
||||
return fetchProcessor.visitFetches( fetchParent, processingState.getInflightQueryPart().getFirstQuerySpec(), this );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.loader.ast.internal;
|
|||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
|
@ -38,7 +37,6 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
|
||||
import org.hibernate.sql.exec.spi.Callback;
|
||||
|
@ -255,8 +253,6 @@ public class MultiIdLoaderStandard<T> implements MultiIdEntityLoader<T> {
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
|
||||
|
||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
|
||||
int offset = 0;
|
||||
|
||||
|
@ -275,6 +271,8 @@ public class MultiIdLoaderStandard<T> implements MultiIdEntityLoader<T> {
|
|||
|
||||
// we should have used all of the JdbcParameter references (created bindings for all)
|
||||
assert offset == jdbcParameters.size();
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
|
||||
.translate( jdbcParameterBindings, QueryOptions.NONE );
|
||||
|
||||
final LoadingEntityCollector loadingEntityCollector;
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.loader.ast.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
|
@ -19,17 +18,14 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.loader.ast.spi.MultiNaturalIdLoadOptions;
|
||||
import org.hibernate.metamodel.mapping.Bindable;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.query.spi.QueryParameterBindings;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstSelectTranslator;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
|
||||
import org.hibernate.sql.exec.spi.Callback;
|
||||
|
@ -95,8 +91,8 @@ public class MultiNaturalIdLoadingBatcher {
|
|||
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
||||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
final SqlAstSelectTranslator sqlAstTranslator = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory );
|
||||
this.jdbcSelect = sqlAstTranslator.translate( sqlSelect );
|
||||
this.jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
|
||||
.translate( null, QueryOptions.NONE );
|
||||
}
|
||||
|
||||
public <E> List<E> multiLoad(Object[] naturalIdValues, MultiNaturalIdLoadOptions options, SharedSessionContractImplementor session) {
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.loader.ast.internal;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
@ -29,7 +28,6 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||
import org.hibernate.sql.exec.spi.Callback;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
|
@ -101,10 +99,7 @@ public class SimpleNaturalIdLoader<T> extends AbstractNaturalIdLoader<T> {
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlSelect );
|
||||
|
||||
final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
|
||||
|
||||
jdbcParamBindings.registerParametersForEachJdbcValue(
|
||||
id,
|
||||
Clause.WHERE,
|
||||
|
@ -112,7 +107,8 @@ public class SimpleNaturalIdLoader<T> extends AbstractNaturalIdLoader<T> {
|
|||
jdbcParameters,
|
||||
session
|
||||
);
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
|
||||
.translate( jdbcParamBindings, QueryOptions.NONE );
|
||||
|
||||
final List<Object[]> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
|
||||
jdbcSelect,
|
||||
|
@ -186,8 +182,6 @@ public class SimpleNaturalIdLoader<T> extends AbstractNaturalIdLoader<T> {
|
|||
);
|
||||
assert jdbcParameters.size() == 1;
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlSelect );
|
||||
|
||||
final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
|
||||
|
||||
final SingularAttributeMapping attributeMapping = naturalIdMapping().getAttribute();
|
||||
|
@ -198,7 +192,8 @@ public class SimpleNaturalIdLoader<T> extends AbstractNaturalIdLoader<T> {
|
|||
jdbcParameters,
|
||||
session
|
||||
);
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
|
||||
.translate( jdbcParamBindings, QueryOptions.NONE );
|
||||
|
||||
final List<?> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
|
||||
jdbcSelect,
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.loader.ast.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
|
@ -26,7 +25,6 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
|
||||
import org.hibernate.sql.exec.spi.Callback;
|
||||
|
@ -102,8 +100,6 @@ public class SingleIdEntityLoaderDynamicBatch<T> extends SingleIdEntityLoaderSup
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
|
||||
|
||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(
|
||||
getLoadable().getIdentifierMapping().getJdbcTypeCount()
|
||||
);
|
||||
|
@ -118,6 +114,8 @@ public class SingleIdEntityLoaderDynamicBatch<T> extends SingleIdEntityLoaderSup
|
|||
);
|
||||
assert offset == jdbcParameters.size();
|
||||
}
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
|
||||
.translate( jdbcParameterBindings, QueryOptions.NONE );
|
||||
|
||||
JdbcSelectExecutorStandardImpl.INSTANCE.list(
|
||||
jdbcSelect,
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.loader.ast.internal;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
|
@ -23,7 +22,6 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
|
||||
import org.hibernate.sql.exec.spi.Callback;
|
||||
|
@ -96,13 +94,10 @@ public class SingleIdLoadPlan<T> implements SingleEntityLoadPlan {
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
|
||||
|
||||
final int jdbcTypeCount = restrictivePart.getJdbcTypeCount();
|
||||
assert jdbcParameters.size() % jdbcTypeCount == 0;
|
||||
|
||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcTypeCount );
|
||||
jdbcSelect.bindFilterJdbcParameters( jdbcParameterBindings );
|
||||
|
||||
int offset = 0;
|
||||
while ( offset < jdbcParameters.size() ) {
|
||||
|
@ -116,6 +111,8 @@ public class SingleIdLoadPlan<T> implements SingleEntityLoadPlan {
|
|||
);
|
||||
}
|
||||
assert offset == jdbcParameters.size();
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
|
||||
.translate( jdbcParameterBindings, QueryOptions.NONE );
|
||||
|
||||
final List list = JdbcSelectExecutorStandardImpl.INSTANCE.list(
|
||||
jdbcSelect,
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.loader.ast.internal;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
|
@ -29,7 +28,6 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||
import org.hibernate.sql.exec.spi.Callback;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
|
@ -86,8 +84,6 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
|
||||
|
||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
|
||||
int offset = jdbcParameterBindings.registerParametersForEachJdbcValue(
|
||||
ukValue,
|
||||
|
@ -97,6 +93,8 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
|
|||
session
|
||||
);
|
||||
assert offset == jdbcParameters.size();
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
|
||||
.translate( jdbcParameterBindings, QueryOptions.NONE );
|
||||
|
||||
final List<Object> list = sessionFactory.getJdbcServices().getJdbcSelectExecutor().list(
|
||||
jdbcSelect,
|
||||
|
@ -164,8 +162,6 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
|
|||
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
|
||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
|
||||
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
|
||||
|
||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
|
||||
int offset = jdbcParameterBindings.registerParametersForEachJdbcValue(
|
||||
ukValue,
|
||||
|
@ -175,6 +171,8 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
|
|||
session
|
||||
);
|
||||
assert offset == jdbcParameters.size();
|
||||
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
|
||||
.translate( jdbcParameterBindings, QueryOptions.NONE );
|
||||
|
||||
final List<Object> list = sessionFactory.getJdbcServices().getJdbcSelectExecutor().list(
|
||||
jdbcSelect,
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
package org.hibernate.metamodel.mapping;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.IndexedConsumer;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
|
@ -59,6 +61,17 @@ public interface EntityValuedModelPart extends FetchableContainer {
|
|||
getEntityMappingType().applySqlSelections( navigablePath, tableGroup, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
default void applySqlSelections(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState,
|
||||
BiConsumer<SqlSelection,JdbcMapping> selectionConsumer) {
|
||||
// this is really only valid for root entity returns, not really many-to-ones, etc.. but this should
|
||||
// really only ever be called as part of creating a root-return.
|
||||
getEntityMappingType().applySqlSelections( navigablePath, tableGroup, creationState, selectionConsumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
default int getJdbcTypeCount() {
|
||||
int span = 0;
|
||||
|
|
|
@ -172,6 +172,29 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
|
|||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
final SqlSelection sqlSelection = resolveSqlSelection( navigablePath, tableGroup, creationState );
|
||||
|
||||
//noinspection unchecked
|
||||
return new BasicResult(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
resultVariable,
|
||||
entityPersister.getIdentifierMapping().getMappedType().getMappedJavaTypeDescriptor(),
|
||||
navigablePath
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySqlSelections(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
resolveSqlSelection( navigablePath, tableGroup, creationState );
|
||||
}
|
||||
|
||||
private SqlSelection resolveSqlSelection(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState()
|
||||
.getSqlExpressionResolver();
|
||||
final TableReference rootTableReference;
|
||||
|
@ -194,7 +217,7 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
|
|||
final Expression expression = expressionResolver.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey( rootTableReference, pkColumnName ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
rootTableReference.getIdentificationVariable(),
|
||||
rootTableReference,
|
||||
pkColumnName,
|
||||
false,
|
||||
null,
|
||||
|
@ -204,45 +227,7 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
|
|||
)
|
||||
);
|
||||
|
||||
final SqlSelection sqlSelection = expressionResolver.resolveSqlSelection(
|
||||
expression,
|
||||
idType.getExpressableJavaTypeDescriptor(),
|
||||
sessionFactory.getTypeConfiguration()
|
||||
);
|
||||
|
||||
//noinspection unchecked
|
||||
return new BasicResult(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
resultVariable,
|
||||
entityPersister.getIdentifierMapping().getMappedType().getMappedJavaTypeDescriptor(),
|
||||
navigablePath
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySqlSelections(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState()
|
||||
.getSqlExpressionResolver();
|
||||
final TableReference rootTableReference = tableGroup.resolveTableReference( rootTable );
|
||||
|
||||
final Expression expression = expressionResolver.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey( rootTableReference, pkColumnName ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
rootTable,
|
||||
pkColumnName,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
( (BasicValuedModelPart) entityPersister.getIdentifierType() ).getJdbcMapping(),
|
||||
sessionFactory
|
||||
)
|
||||
);
|
||||
|
||||
// the act of resolving the expression -> selection applies it
|
||||
expressionResolver.resolveSqlSelection(
|
||||
return expressionResolver.resolveSqlSelection(
|
||||
expression,
|
||||
idType.getExpressableJavaTypeDescriptor(),
|
||||
sessionFactory.getTypeConfiguration()
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue