Add support for FETCH clause, CTEs and set operations

This commit is contained in:
Christian Beikov 2020-12-17 18:16:09 +01:00
parent f54072df4e
commit 4efffca23b
300 changed files with 12093 additions and 4462 deletions

View File

@ -4,15 +4,15 @@ goal=
if [ "$RDBMS" == "derby" ]; then if [ "$RDBMS" == "derby" ]; then
goal="-Pdb=derby" goal="-Pdb=derby"
elif [ "$RDBMS" == "mariadb" ]; then elif [ "$RDBMS" == "mariadb" ]; then
goal="-Pdb=mariadb" goal="-Pdb=mariadb_ci"
elif [ "$RDBMS" == "postgresql" ]; then elif [ "$RDBMS" == "postgresql" ]; then
goal="-Pdb=pgsql" goal="-Pdb=pgsql_ci"
elif [ "$RDBMS" == "oracle" ]; then 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 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 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 fi
exec ./gradlew check ${goal} -Plog-test-progress=true --stacktrace exec ./gradlew check ${goal} -Plog-test-progress=true --stacktrace

View File

@ -12,7 +12,7 @@ mysql_8_0() {
mariadb() { mariadb() {
docker rm -f mariadb || true 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() { 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 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() { db2() {
docker rm -f db2 || true 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 # Give the container some time to start
OUTPUT= OUTPUT=
while [[ $OUTPUT != *"Setup has completed"* ]]; do while [[ $OUTPUT != *"INSTANCE"* ]]; do
echo "Waiting for DB2 to start..." echo "Waiting for DB2 to start..."
sleep 10 sleep 10
OUTPUT=$(docker logs db2) OUTPUT=$(docker logs db2)
@ -36,6 +41,22 @@ db2() {
mssql() { mssql() {
docker rm -f mssql || true 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 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() { oracle() {
@ -52,6 +73,7 @@ if [ -z ${1} ]; then
echo -e "\tmysql_8_0" echo -e "\tmysql_8_0"
echo -e "\tmariadb" echo -e "\tmariadb"
echo -e "\tpostgresql_9_5" echo -e "\tpostgresql_9_5"
echo -e "\tpostgresql_13"
echo -e "\tdb2" echo -e "\tdb2"
echo -e "\tmssql" echo -e "\tmssql"
echo -e "\toracle" echo -e "\toracle"

View File

@ -10,6 +10,7 @@ import org.apache.tools.ant.filters.ReplaceTokens
// build a map of the database settings to use. // build a map of the database settings to use.
ext { ext {
db = project.hasProperty('db') ? project.getProperty('db') : 'h2' db = project.hasProperty('db') ? project.getProperty('db') : 'h2'
def dbHost = System.getProperty( 'dbHost', 'localhost' )
dbBundle = [ dbBundle = [
h2 : [ h2 : [
'db.dialect' : 'org.hibernate.dialect.H2Dialect', 'db.dialect' : 'org.hibernate.dialect.H2Dialect',
@ -26,47 +27,61 @@ ext {
'jdbc.url' : 'jdbc:hsqldb:mem:test' 'jdbc.url' : 'jdbc:hsqldb:mem:test'
], ],
derby : [ derby : [
'db.dialect' : 'org.hibernate.dialect.DerbyTenSevenDialect', 'db.dialect' : 'org.hibernate.dialect.DerbyDialect',
'jdbc.driver': 'org.apache.derby.jdbc.EmbeddedDriver', 'jdbc.driver': 'org.apache.derby.jdbc.EmbeddedDriver',
'jdbc.user' : 'hibernate_orm_test', 'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test', 'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:derby:target/tmp/derby/hibernate_orm_test;databaseName=hibernate_orm_test;create=true' 'jdbc.url' : 'jdbc:derby:target/tmp/derby/hibernate_orm_test;databaseName=hibernate_orm_test;create=true'
], ],
pgsql : [ pgsql : [
'db.dialect' : 'org.hibernate.dialect.PostgreSQL95Dialect', 'db.dialect' : 'org.hibernate.dialect.PostgreSQLDialect',
'jdbc.driver': 'org.postgresql.Driver', 'jdbc.driver': 'org.postgresql.Driver',
'jdbc.user' : 'hibernate_orm_test', 'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test', 'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:postgresql:hibernate_orm_test' 'jdbc.url' : 'jdbc:postgresql:hibernate_orm_test'
], ],
pgsql_docker : [ pgsql_docker : [
'db.dialect' : 'org.hibernate.dialect.PostgreSQL95Dialect', 'db.dialect' : 'org.hibernate.dialect.PostgreSQLDialect',
'jdbc.driver': 'org.postgresql.Driver', 'jdbc.driver': 'org.postgresql.Driver',
'jdbc.user' : 'hibernate_orm_test', 'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test', 'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:postgresql://127.0.0.1/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 : [ mysql : [
'db.dialect' : 'org.hibernate.dialect.MySQL57Dialect', 'db.dialect' : 'org.hibernate.dialect.MySQLDialect',
'jdbc.driver': 'com.mysql.jdbc.Driver', 'jdbc.driver': 'com.mysql.jdbc.Driver',
'jdbc.user' : 'hibernateormtest', 'jdbc.user' : 'hibernateormtest',
'jdbc.pass' : 'hibernateormtest', 'jdbc.pass' : 'hibernateormtest',
'jdbc.url' : 'jdbc:mysql://localhost/hibernate_orm_test' 'jdbc.url' : 'jdbc:mysql://localhost/hibernate_orm_test'
], ],
mysql_docker : [ mysql_docker : [
'db.dialect' : 'org.hibernate.dialect.MySQL57Dialect', 'db.dialect' : 'org.hibernate.dialect.MySQLDialect',
'jdbc.driver': 'com.mysql.jdbc.Driver', 'jdbc.driver': 'com.mysql.jdbc.Driver',
'jdbc.user' : 'hibernate_orm_test', 'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test', 'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:mysql://127.0.0.1/hibernate_orm_test?useSSL=false' 'jdbc.url' : 'jdbc:mysql://127.0.0.1/hibernate_orm_test?useSSL=false'
], ],
mariadb : [ mariadb : [
'db.dialect' : 'org.hibernate.dialect.MariaDB103Dialect', 'db.dialect' : 'org.hibernate.dialect.MariaDBDialect',
'jdbc.driver': 'org.mariadb.jdbc.Driver', 'jdbc.driver': 'org.mariadb.jdbc.Driver',
'jdbc.user' : 'hibernate_orm_test', 'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test', 'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:mariadb://127.0.0.1/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 : [ postgis : [
'db.dialect' : 'org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect', 'db.dialect' : 'org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect',
'jdbc.driver': 'org.postgresql.Driver', 'jdbc.driver': 'org.postgresql.Driver',
@ -75,7 +90,7 @@ ext {
'jdbc.url' : 'jdbc:postgresql:hibernate_orm_test' 'jdbc.url' : 'jdbc:postgresql:hibernate_orm_test'
], ],
oracle : [ oracle : [
'db.dialect' : 'org.hibernate.dialect.Oracle10gDialect', 'db.dialect' : 'org.hibernate.dialect.OracleDialect',
'jdbc.driver': 'oracle.jdbc.OracleDriver', 'jdbc.driver': 'oracle.jdbc.OracleDriver',
'jdbc.user' : 'hibernate_orm_test', 'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : '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: // 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 // 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 : [ oracle_docker : [
'db.dialect' : 'org.hibernate.dialect.Oracle12cDialect', 'db.dialect' : 'org.hibernate.dialect.OracleDialect',
'jdbc.driver': 'oracle.jdbc.OracleDriver', 'jdbc.driver': 'oracle.jdbc.OracleDriver',
'jdbc.user' : 'sys as sysdba', 'jdbc.user' : 'sys as sysdba',
'jdbc.pass' : 'Oradoc_db1', 'jdbc.pass' : 'Oradoc_db1',
'jdbc.url' : 'jdbc:oracle:thin:@localhost:1521:ORCLCDB' '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 : [ mssql : [
'db.dialect' : 'org.hibernate.dialect.SQLServer2012Dialect', 'db.dialect' : 'org.hibernate.dialect.SQLServerDialect',
'jdbc.driver': 'com.microsoft.sqlserver.jdbc.SQLServerDriver', 'jdbc.driver': 'com.microsoft.sqlserver.jdbc.SQLServerDriver',
'jdbc.user' : 'hibernate_orm_test', 'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test', 'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=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 : [ informix : [
'db.dialect' : 'org.hibernate.dialect.InformixDialect', 'db.dialect' : 'org.hibernate.dialect.InformixDialect',
'jdbc.driver': 'com.informix.jdbc.IfxDriver', 'jdbc.driver': 'com.informix.jdbc.IfxDriver',
@ -112,6 +141,13 @@ ext {
'jdbc.pass' : 'db2inst1-pwd', 'jdbc.pass' : 'db2inst1-pwd',
'jdbc.url' : 'jdbc:db2://127.0.0.1:50000/hibern8' '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 : [ hana : [
'db.dialect' : 'org.hibernate.dialect.HANAColumnStoreDialect', 'db.dialect' : 'org.hibernate.dialect.HANAColumnStoreDialect',
'jdbc.driver': 'com.sap.db.jdbc.Driver', 'jdbc.driver': 'com.sap.db.jdbc.Driver',
@ -134,7 +170,7 @@ ext {
'jdbc.url' : 'jdbc:sap://localhost:39015/' 'jdbc.url' : 'jdbc:sap://localhost:39015/'
], ],
cockroachdb : [ 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. // CockroachDB uses the same pgwire protocol as PostgreSQL, so the driver is the same.
'jdbc.driver': 'org.postgresql.Driver', 'jdbc.driver': 'org.postgresql.Driver',
'jdbc.user' : 'root', 'jdbc.user' : 'root',

View File

@ -111,10 +111,10 @@ dependencies {
testRuntime( libraries.hana ) testRuntime( libraries.hana )
testRuntime( libraries.cockroachdb ) testRuntime( libraries.cockroachdb )
if ( db.equalsIgnoreCase( 'oracle' ) || db.equalsIgnoreCase( 'oracle_docker' ) ) { if ( db.startsWith( 'oracle' ) ) {
testRuntime( libraries.oracle ) testRuntime( libraries.oracle )
} }
else if ( db.equalsIgnoreCase( 'db2' ) ) { else if ( db.startsWith( 'db2' ) ) {
testRuntime( libraries.db2 ) testRuntime( libraries.db2 )
} }
else if ( db.equalsIgnoreCase( 'hana' ) ) { else if ( db.equalsIgnoreCase( 'hana' ) ) {

View File

@ -121,7 +121,7 @@ PLUS : '+';
MINUS : '-'; MINUS : '-';
ASTERISK : '*'; ASTERISK : '*';
SLASH : '/'; SLASH : '/';
PERCENT : '%'; PERCENT_OP : '%';
AMPERSAND : '&'; AMPERSAND : '&';
SEMICOLON : ';'; SEMICOLON : ';';
COLON : ':'; COLON : ':';
@ -176,6 +176,7 @@ END : [eE] [nN] [dD];
ENTRY : [eE] [nN] [tT] [rR] [yY]; ENTRY : [eE] [nN] [tT] [rR] [yY];
ESCAPE : [eE] [sS] [cC] [aA] [pP] [eE]; ESCAPE : [eE] [sS] [cC] [aA] [pP] [eE];
EVERY : [eE] [vV] [eE] [rR] [yY]; EVERY : [eE] [vV] [eE] [rR] [yY];
EXCEPT : [eE] [xX] [cC] [eE] [pP] [tT];
EXISTS : [eE] [xX] [iI] [sS] [tT] [sS]; EXISTS : [eE] [xX] [iI] [sS] [tT] [sS];
EXP : [eE] [xX] [pP]; EXP : [eE] [xX] [pP];
EXTRACT : [eE] [xX] [tT] [rR] [aA] [cC] [tT]; EXTRACT : [eE] [xX] [tT] [rR] [aA] [cC] [tT];
@ -197,6 +198,7 @@ INDEX : [iI] [nN] [dD] [eE] [xX];
INNER : [iI] [nN] [nN] [eE] [rR]; INNER : [iI] [nN] [nN] [eE] [rR];
INSERT : [iI] [nN] [sS] [eE] [rR] [tT]; INSERT : [iI] [nN] [sS] [eE] [rR] [tT];
INSTANT : [iI] [nN] [sS] [tT] [aA] [nN] [tT]; INSTANT : [iI] [nN] [sS] [tT] [aA] [nN] [tT];
INTERSECT : [iI] [nN] [tT] [eE] [rR] [sS] [eE] [cC] [tT];
INTO : [iI] [nN] [tT] [oO]; INTO : [iI] [nN] [tT] [oO];
IS : [iI] [sS]; IS : [iI] [sS];
JOIN : [jJ] [oO] [iI] [nN]; JOIN : [jJ] [oO] [iI] [nN];
@ -230,6 +232,7 @@ MINUTE : [mM] [iI] [nN] [uU] [tT] [eE];
MOD : [mM] [oO] [dD]; MOD : [mM] [oO] [dD];
MONTH : [mM] [oO] [nN] [tT] [hH]; MONTH : [mM] [oO] [nN] [tT] [hH];
NANOSECOND : [nN] [aA] [nN] [oO] [sS] [eE] [cC] [oO] [nN] [dD]; NANOSECOND : [nN] [aA] [nN] [oO] [sS] [eE] [cC] [oO] [nN] [dD];
NEXT : [nN] [eE] [xX] [tT];
NEW : [nN] [eE] [wW]; NEW : [nN] [eE] [wW];
NOT : [nN] [oO] [tT]; NOT : [nN] [oO] [tT];
NULLIF : [nN] [uU] [lL] [lL] [iI] [fF]; NULLIF : [nN] [uU] [lL] [lL] [iI] [fF];
@ -239,11 +242,13 @@ OF : [oO] [fF];
OFFSET : [oO] [fF] [fF] [sS] [eE] [tT]; OFFSET : [oO] [fF] [fF] [sS] [eE] [tT];
OFFSET_DATETIME : [oO] [fF] [fF] [sS] [eE] [tT] '_' [dD] [aA] [tT] [eE] [tT] [iI] [mM] [eE]; OFFSET_DATETIME : [oO] [fF] [fF] [sS] [eE] [tT] '_' [dD] [aA] [tT] [eE] [tT] [iI] [mM] [eE];
ON : [oO] [nN]; ON : [oO] [nN];
ONLY : [oO] [nN] [lL] [yY];
OR : [oO] [rR]; OR : [oO] [rR];
ORDER : [oO] [rR] [dD] [eE] [rR]; ORDER : [oO] [rR] [dD] [eE] [rR];
OUTER : [oO] [uU] [tT] [eE] [rR]; OUTER : [oO] [uU] [tT] [eE] [rR];
OVERLAY : [oO] [vV] [eE] [rR] [lL] [aA] [yY]; OVERLAY : [oO] [vV] [eE] [rR] [lL] [aA] [yY];
PAD : [pP] [aA] [dD]; PAD : [pP] [aA] [dD];
PERCENT : [pP] [eE] [rR] [cC] [eE] [nN] [tT];
PLACING : [pP] [lL] [aA] [cC] [iI] [nN] [gG]; PLACING : [pP] [lL] [aA] [cC] [iI] [nN] [gG];
POSITION : [pP] [oO] [sS] [iI] [tT] [iI] [oO] [nN]; POSITION : [pP] [oO] [sS] [iI] [tT] [iI] [oO] [nN];
POWER : [pP] [oO] [wW] [eE] [rR]; POWER : [pP] [oO] [wW] [eE] [rR];
@ -252,6 +257,8 @@ REPLACE : [rR] [eE] [pP] [lL] [aA] [cC] [eE];
RIGHT : [rR] [iI] [gG] [hH] [tT]; RIGHT : [rR] [iI] [gG] [hH] [tT];
ROLLUP : [rR] [oO] [lL] [lL] [uU] [pP]; ROLLUP : [rR] [oO] [lL] [lL] [uU] [pP];
ROUND : [rR] [oO] [uU] [nN] [dD]; ROUND : [rR] [oO] [uU] [nN] [dD];
ROWS : [rR] [oO] [wW] [sS];
ROW : [rR] [oO] [wW];
SECOND : [sS] [eE] [cC] [oO] [nN] [dD]; SECOND : [sS] [eE] [cC] [oO] [nN] [dD];
SELECT : [sS] [eE] [lL] [eE] [cC] [tT]; SELECT : [sS] [eE] [lL] [eE] [cC] [tT];
SET : [sS] [eE] [tT]; SET : [sS] [eE] [tT];
@ -263,6 +270,7 @@ STR : [sS] [tT] [rR];
SUBSTRING : [sS] [uU] [bB] [sS] [tT] [rR] [iI] [nN] [gG]; SUBSTRING : [sS] [uU] [bB] [sS] [tT] [rR] [iI] [nN] [gG];
SUM : [sS] [uU] [mM]; SUM : [sS] [uU] [mM];
THEN : [tT] [hH] [eE] [nN]; THEN : [tT] [hH] [eE] [nN];
TIES : [tT] [iI] [eE] [sS];
TIME : [tT] [iI] [mM] [eE]; TIME : [tT] [iI] [mM] [eE];
TIMESTAMP : [tT] [iI] [mM] [eE] [sS] [tT] [aA] [mM] [pP]; TIMESTAMP : [tT] [iI] [mM] [eE] [sS] [tT] [aA] [mM] [pP];
TIMEZONE_HOUR : [tT] [iI] [mM] [eE] [zZ] [oO] [nN] [eE] '_' [hH] [oO] [uU] [rR]; 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]; TREAT : [tT] [rR] [eE] [aA] [tT];
TRIM : [tT] [rR] [iI] [mM]; TRIM : [tT] [rR] [iI] [mM];
TYPE : [tT] [yY] [pP] [eE]; TYPE : [tT] [yY] [pP] [eE];
UNION : [uU] [nN] [iI] [oO] [nN];
UPDATE : [uU] [pP] [dD] [aA] [tT] [eE]; UPDATE : [uU] [pP] [dD] [aA] [tT] [eE];
UPPER : [uU] [pP] [pP] [eE] [rR]; UPPER : [uU] [pP] [pP] [eE] [rR];
VALUE : [vV] [aA] [lL] [uU] [eE]; VALUE : [vV] [aA] [lL] [uU] [eE];

View File

@ -28,11 +28,11 @@ statement
; ;
selectStatement selectStatement
: querySpec : queryExpression
; ;
subQuery subQuery
: querySpec : queryExpression
; ;
dmlTarget dmlTarget
@ -56,7 +56,7 @@ assignment
; ;
insertStatement insertStatement
: INSERT INTO? dmlTarget targetFieldsSpec (querySpec | valuesList) : INSERT INTO? dmlTarget targetFieldsSpec (queryExpression | valuesList)
; ;
targetFieldsSpec targetFieldsSpec
@ -74,9 +74,30 @@ values
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// QUERY SPEC - general structure of root sqm or sub sqm // 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 querySpec
: selectClause fromClause? whereClause? ( groupByClause havingClause? )? orderByClause? limitClause? offsetClause? // TODO: add with clause
| fromClause whereClause? ( groupByClause havingClause? )? selectClause? orderByClause? limitClause? offsetClause? : selectClause fromClause? whereClause? ( groupByClause havingClause? )?
| fromClause whereClause? ( groupByClause havingClause? )? selectClause?
; ;
@ -340,16 +361,27 @@ orderingSpecification
// LIMIT/OFFSET clause // LIMIT/OFFSET clause
limitClause limitClause
: LIMIT parameterOrNumberLiteral : LIMIT parameterOrIntegerLiteral
; ;
offsetClause offsetClause
: OFFSET parameterOrNumberLiteral : OFFSET parameterOrIntegerLiteral (ROW | ROWS)?
;
fetchClause
: FETCH (FIRST | NEXT) (parameterOrIntegerLiteral | parameterOrNumberLiteral PERCENT) (ROW | ROWS) (ONLY | WITH TIES)
;
parameterOrIntegerLiteral
: parameter
| INTEGER_LITERAL
; ;
parameterOrNumberLiteral parameterOrNumberLiteral
: parameter : parameter
| INTEGER_LITERAL | INTEGER_LITERAL
| FLOAT_LITERAL
| DOUBLE_LITERAL
; ;
@ -427,7 +459,7 @@ primaryExpression
multiplicativeOperator multiplicativeOperator
: SLASH : SLASH
| PERCENT | PERCENT_OP
| ASTERISK | ASTERISK
; ;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -75,6 +75,14 @@ public class LockOptions implements Serializable {
this.lockMode = lockMode; 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. * 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() ); destination.setFollowOnLocking( source.getFollowOnLocking() );
return destination; 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;
}
} }

View File

@ -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;
}

View File

@ -15,17 +15,53 @@ public enum NullPrecedence {
/** /**
* Null precedence not specified. Relies on the RDBMS implementation. * 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. * 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. * 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 * Interprets a string representation of a NullPrecedence, returning {@code null} by default. For

View File

@ -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;
}
}

View File

@ -25,6 +25,7 @@ import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.engine.jdbc.*; import org.hibernate.engine.jdbc.*;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.env.spi.*; import org.hibernate.engine.jdbc.env.spi.*;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.exception.LockTimeoutException; import org.hibernate.exception.LockTimeoutException;
@ -39,6 +40,10 @@ import org.hibernate.procedure.spi.CallableStatementSupport;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.service.ServiceRegistry; 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.internal.SequenceInformationExtractorHANADatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.tool.schema.internal.StandardTableExporter; import org.hibernate.tool.schema.internal.StandardTableExporter;
@ -821,6 +826,17 @@ public abstract class AbstractHANADialect extends Dialect {
CommonFunctionFactory.currentUtcdatetimetimestamp( queryEngine ); 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 * HANA has no extract() function, but we can emulate
* it using the appropriate named functions instead of * it using the appropriate named functions instead of
@ -1158,11 +1174,6 @@ public abstract class AbstractHANADialect extends Dialect {
return true; return true;
} }
@Override
public boolean supportsUnionAll() {
return true;
}
@Override @Override
public boolean dropConstraints() { public boolean dropConstraints() {
return false; return false;

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.NullOrdering;
import org.hibernate.boot.TempTableDdlTransactionHandling; import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.CommonFunctionFactory; import org.hibernate.dialect.function.CommonFunctionFactory;
@ -223,6 +224,11 @@ abstract class AbstractTransactSQLDialect extends Dialect {
return GroupByConstantRenderingStrategy.COLUMN_REFERENCE; return GroupByConstantRenderingStrategy.COLUMN_REFERENCE;
} }
@Override
public NullOrdering getNullOrdering() {
return NullOrdering.SMALLEST;
}
@Override @Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy( public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType entityDescriptor, EntityMappingType entityDescriptor,
@ -254,11 +260,6 @@ abstract class AbstractTransactSQLDialect extends Dialect {
return false; return false;
} }
@Override
public boolean supportsUnionAll() {
return true;
}
@Override @Override
public boolean supportsExistsInSelect() { public boolean supportsExistsInSelect() {
return false; return false;

View File

@ -16,9 +16,15 @@ import org.hibernate.dialect.pagination.LimitLimitHandler;
import org.hibernate.dialect.sequence.CUBRIDSequenceSupport; import org.hibernate.dialect.sequence.CUBRIDSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine; 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.internal.SequenceInformationExtractorCUBRIDDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
@ -238,11 +244,6 @@ public class CUBRIDDialect extends Dialect {
return ""; return "";
} }
@Override
public boolean supportsUnionAll() {
return true;
}
@Override @Override
public boolean supportsCurrentTimestampSelection() { public boolean supportsCurrentTimestampSelection() {
return true; return true;
@ -273,6 +274,17 @@ public class CUBRIDDialect extends Dialect {
return false; 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 @Override
public LimitHandler getLimitHandler() { public LimitHandler getLimitHandler() {
return LimitLimitHandler.INSTANCE; return LimitLimitHandler.INSTANCE;

View File

@ -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
}
}

View File

@ -16,6 +16,7 @@ import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.TopLimitHandler; import org.hibernate.dialect.pagination.TopLimitHandler;
import org.hibernate.dialect.sequence.CacheSequenceSupport; import org.hibernate.dialect.sequence.CacheSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.exception.DataException; import org.hibernate.exception.DataException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
@ -27,6 +28,11 @@ import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.CacheJoinFragment; import org.hibernate.sql.CacheJoinFragment;
import org.hibernate.sql.JoinFragment; 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 org.hibernate.type.StandardBasicTypes;
import java.sql.CallableStatement; 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) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LIMIT support (ala TOP) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override @Override

View File

@ -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
}
}

View File

@ -12,8 +12,14 @@ import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport; import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine; 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.StandardBasicTypes;
import java.sql.Types; import java.sql.Types;
@ -169,11 +175,6 @@ public class CockroachDialect extends Dialect {
return true; return true;
} }
@Override
public boolean supportsUnionAll() {
return true;
}
@Override @Override
public String getNoColumnsInsertString() { public String getNoColumnsInsertString() {
return "default values"; 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"; 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 @Override
public boolean supportsNationalizedTypes() { public boolean supportsNationalizedTypes() {
return false; return false;

View File

@ -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
}
}

View File

@ -22,6 +22,7 @@ import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.unique.DB2UniqueDelegate; import org.hibernate.dialect.unique.DB2UniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate; import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.LockTimeoutException; import org.hibernate.exception.LockTimeoutException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.internal.util.JdbcExceptionHelper; 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.CastType;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction; import org.hibernate.query.sqm.mutation.internal.cte.CteStrategy;
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.spi.SqmMultiTableMutationStrategy; 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.SequenceInformationExtractorDB2DatabaseImpl;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
@ -407,11 +410,6 @@ public class DB2Dialect extends Dialect {
return "nullif(" + literal + ", " + literal + ')'; return "nullif(" + literal + ", " + literal + ')';
} }
@Override
public boolean supportsUnionAll() {
return true;
}
@Override @Override
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException { public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
return col; return col;
@ -437,47 +435,7 @@ public class DB2Dialect extends Dialect {
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy( public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor, EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) { RuntimeModelCreationContext runtimeModelCreationContext) {
return new CteStrategy( rootEntityDescriptor, 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
// );
} }
@Override @Override
@ -639,6 +597,17 @@ public class DB2Dialect extends Dialect {
return false; 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... * Handle DB2 "support" for null precedence...
* *

View File

@ -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
}
}

View File

@ -15,10 +15,15 @@ import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.DB2iSequenceSupport; import org.hibernate.dialect.sequence.DB2iSequenceSupport;
import org.hibernate.dialect.sequence.NoSequenceSupport; import org.hibernate.dialect.sequence.NoSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.unique.DB2UniqueDelegate;
import org.hibernate.dialect.unique.DefaultUniqueDelegate; import org.hibernate.dialect.unique.DefaultUniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate; import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; 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. * An SQL dialect for DB2 for iSeries previously known as DB2/400.
@ -90,10 +95,10 @@ public class DB2iDialect extends DB2Dialect {
@Override @Override
public LimitHandler getLimitHandler() { public LimitHandler getLimitHandler() {
if ( getIVersion() >= 730) { if ( getIVersion() >= 730) {
return LegacyDB2LimitHandler.INSTANCE; return FetchLimitHandler.INSTANCE;
} }
else { else {
return FetchLimitHandler.INSTANCE; return LegacyDB2LimitHandler.INSTANCE;
} }
} }
@ -106,4 +111,15 @@ public class DB2iDialect extends DB2Dialect {
return new DB2390IdentityColumnSupport(); 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 );
}
};
}
} }

View File

@ -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;
}
}

View File

@ -18,7 +18,13 @@ import org.hibernate.dialect.sequence.DB2390SequenceSupport;
import org.hibernate.dialect.sequence.NoSequenceSupport; import org.hibernate.dialect.sequence.NoSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.TemporalUnit; 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. * 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(")"); pattern.append(")");
return pattern.toString(); 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 );
}
};
}
} }

View File

@ -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;
}
}

View File

@ -23,6 +23,7 @@ import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder; import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.LockTimeoutException; import org.hibernate.exception.LockTimeoutException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.internal.util.JdbcExceptionHelper; 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.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.CaseFragment; import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DerbyCaseFragment; 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.SequenceInformationExtractorDerbyDatabaseImpl;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
@ -202,6 +208,17 @@ public class DerbyDialect extends Dialect {
.register(); .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 * Derby doesn't have an extract() function, and has
* no functions at all for calendaring, but we can * no functions at all for calendaring, but we can
@ -410,11 +427,6 @@ public class DerbyDialect extends Dialect {
return false; return false;
} }
@Override
public boolean supportsUnionAll() {
return true;
}
@Override @Override
public boolean supportsCurrentTimestampSelection() { public boolean supportsCurrentTimestampSelection() {
return true; return true;

View File

@ -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;
}
}

View File

@ -11,6 +11,7 @@ import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.NullOrdering;
import org.hibernate.NullPrecedence; import org.hibernate.NullPrecedence;
import org.hibernate.ScrollMode; import org.hibernate.ScrollMode;
import org.hibernate.boot.model.TypeContributions; 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 * Does this dialect support UNION ALL.
* variant of UNION?
* *
* @return True if UNION ALL is supported; false otherwise. * @return True if UNION ALL is supported; false otherwise.
*/ */
public boolean supportsUnionAll() { public boolean supportsUnionAll() {
return false; return true;
} }
// miscellaneous support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // miscellaneous support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2690,6 +2689,15 @@ public abstract class Dialect implements ConversionContext {
return true; return true;
} }
/**
* Returns the ordering of null.
*
* @since 6.0.0
*/
public NullOrdering getNullOrdering() {
return NullOrdering.GREATEST;
}
public boolean supportsNullPrecedence() { public boolean supportsNullPrecedence() {
return true; return true;
} }
@ -2705,7 +2713,9 @@ public abstract class Dialect implements ConversionContext {
* if expression has not been explicitly specified. * if expression has not been explicitly specified.
* @param nulls Nulls precedence. Default value: {@link NullPrecedence#NONE}. * @param nulls Nulls precedence. Default value: {@link NullPrecedence#NONE}.
* @return Renders single element of {@code ORDER BY} clause. * @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) { public String renderOrderByElement(String expression, String collation, String order, NullPrecedence nulls) {
final StringBuilder orderByElement = new StringBuilder( expression ); final StringBuilder orderByElement = new StringBuilder( expression );
if ( collation != null ) { if ( collation != null ) {
@ -2980,7 +2990,9 @@ public abstract class Dialect implements ConversionContext {
* @param expression The expression to negate * @param expression The expression to negate
* *
* @return The negated expression * @return The negated expression
* @deprecated todo (6.0): Remove
*/ */
@Deprecated
public String getNotExpression(String expression) { public String getNotExpression(String expression) {
return "not " + expression; return "not " + expression;
} }
@ -3215,14 +3227,6 @@ public abstract class Dialect implements ConversionContext {
return String.format( "\'%s\'", escapeLiteral( literal ) ); 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()}, * Check whether the JDBC {@link java.sql.Connection} supports creating LOBs via {@link Connection#createBlob()},
* {@link Connection#createNClob()} or {@link Connection#createClob()}. * {@link Connection#createNClob()} or {@link Connection#createClob()}.
@ -3249,17 +3253,16 @@ public abstract class Dialect implements ConversionContext {
*/ */
public String addSqlHintOrComment( public String addSqlHintOrComment(
String sql, String sql,
// QueryParameters parameters, QueryOptions queryOptions,
boolean commentsEnabled) { boolean commentsEnabled) {
// Keep this here, rather than moving to Select. Some Dialects may need the hint to be appended to the very // 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. // end or beginning of the finalized SQL statement, so wait until everything is processed.
// if ( parameters.getQueryHints() != null && parameters.getQueryHints().size() > 0 ) { if ( queryOptions.getDatabaseHints() != null && queryOptions.getDatabaseHints().size() > 0 ) {
// sql = getQueryHintString( sql, parameters.getQueryHints() ); sql = getQueryHintString( sql, queryOptions.getDatabaseHints() );
// } }
// if ( commentsEnabled && parameters.getComment() != null ){ if ( commentsEnabled && queryOptions.getComment() != null ) {
// sql = prependComment( sql, parameters.getComment() ); sql = prependComment( sql, queryOptions.getComment() );
// } }
return sql; return sql;
} }
@ -3296,7 +3299,7 @@ public abstract class Dialect implements ConversionContext {
* Note that {@link SessionFactoryOptions#getCustomSqmTranslatorFactory()} has higher * Note that {@link SessionFactoryOptions#getCustomSqmTranslatorFactory()} has higher
* precedence as it comes directly from the user config * 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() * @see QueryEngine#getSqmTranslatorFactory()
*/ */
public SqmTranslatorFactory getSqmTranslatorFactory() { public SqmTranslatorFactory getSqmTranslatorFactory() {

View File

@ -22,6 +22,7 @@ import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder; import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.exception.LockTimeoutException; 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.IdTable;
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter; import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; 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.SequenceInformationExtractorFirebirdDatabaseImpl;
import org.hibernate.tool.schema.extract.internal.SequenceNameExtractorImpl; import org.hibernate.tool.schema.extract.internal.SequenceNameExtractorImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
@ -196,6 +202,17 @@ public class FirebirdDialect extends Dialect {
).setArgumentListSignature("(pattern, string[, start])"); ).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} * Firebird 2.5 doesn't have a real {@link java.sql.Types#BOOLEAN}
* type, so... * type, so...
@ -289,11 +306,6 @@ public class FirebirdDialect extends Dialect {
return "add"; return "add";
} }
@Override
public boolean supportsUnionAll() {
return true;
}
@Override @Override
public String getNoColumnsInsertString() { public String getNoColumnsInsertString() {
return "default values"; return "default values";

View File

@ -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;
}
}

View File

@ -10,6 +10,7 @@ import java.sql.Types;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import org.hibernate.NullOrdering;
import org.hibernate.PessimisticLockException; import org.hibernate.PessimisticLockException;
import org.hibernate.boot.TempTableDdlTransactionHandling; import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.cfg.AvailableSettings; 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.H2SequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate; 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.IdTable;
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy; import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; 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.SequenceInformationExtractorH2DatabaseImpl;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
@ -72,31 +79,35 @@ public class H2Dialect extends Dialect {
} }
public H2Dialect(int version, int buildId) { public H2Dialect(int version, int buildId) {
this(version + buildId);
}
public H2Dialect(int version) {
super(); super();
this.version = version; this.version = version;
//TODO: actually I think all builds of 1.4 support OFFSET FETCH // https://github.com/h2database/h2database/commit/b2cdf84e0b84eb8a482fa7dccdccc1ab95241440
limitHandler = version > 140 || version == 140 && buildId >= 199 limitHandler = version >= 104195
? OffsetFetchLimitHandler.INSTANCE ? OffsetFetchLimitHandler.INSTANCE
: LimitOffsetLimitHandler.INSTANCE; : LimitOffsetLimitHandler.INSTANCE;
//Note: H2 'bit' is a synonym for 'boolean', not a proper bit type //Note: H2 'bit' is a synonym for 'boolean', not a proper bit type
// registerColumnType( Types.BIT, "bit" ); // registerColumnType( Types.BIT, "bit" );
final int majorVersion = version / 100; if ( version < 102139 ) {
final int minorVersion = version % 100 / 10; final int majorVersion = version / 100000;
if ( version < 120 || version == 120 && buildId < 139 ) { final int minorVersion = version % 100000 / 1000;
final int buildId = version % 1000;
LOG.unsupportedMultiTableBulkHqlJpaql( majorVersion, minorVersion, buildId ); 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 // 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 ); getDefaultProperties().setProperty( AvailableSettings.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
// http://code.google.com/p/h2database/issues/detail?id=235 // http://code.google.com/p/h2database/issues/detail?id=235
getDefaultProperties().setProperty( AvailableSettings.NON_CONTEXTUAL_LOB_CREATION, "true" ); getDefaultProperties().setProperty( AvailableSettings.NON_CONTEXTUAL_LOB_CREATION, "true" );
if ( buildId >= 32 ) { if ( version >= 104032 ) {
this.sequenceInformationExtractor = buildId >= 201 this.sequenceInformationExtractor = version >= 104201
? SequenceInformationExtractorLegacyImpl.INSTANCE ? SequenceInformationExtractorLegacyImpl.INSTANCE
: SequenceInformationExtractorH2DatabaseImpl.INSTANCE; : SequenceInformationExtractorH2DatabaseImpl.INSTANCE;
this.querySequenceString = "select * from INFORMATION_SCHEMA.SEQUENCES"; this.querySequenceString = "select * from INFORMATION_SCHEMA.SEQUENCES";
@ -115,8 +126,8 @@ public class H2Dialect extends Dialect {
public H2Dialect(DialectResolutionInfo info) { public H2Dialect(DialectResolutionInfo info) {
this( this(
info.getDatabaseMajorVersion()*100 info.getDatabaseMajorVersion() * 100000
+ info.getDatabaseMinorVersion()*10, + info.getDatabaseMinorVersion() * 1000,
parseBuildId( info ) parseBuildId( info )
); );
} }
@ -174,6 +185,17 @@ public class H2Dialect extends Dialect {
CommonFunctionFactory.rownum( queryEngine ); 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 * In H2, the extract() function does not return
* fractional seconds for the the field * fractional seconds for the the field
@ -269,6 +291,11 @@ public class H2Dialect extends Dialect {
return "from dual"; return "from dual";
} }
@Override
public NullOrdering getNullOrdering() {
return NullOrdering.FIRST;
}
@Override @Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy( public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType entityDescriptor, EntityMappingType entityDescriptor,
@ -342,11 +369,6 @@ public class H2Dialect extends Dialect {
return "call current_timestamp()"; return "call current_timestamp()";
} }
@Override
public boolean supportsUnionAll() {
return true;
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -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;
}
}

View File

@ -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
}
}

View File

@ -13,6 +13,7 @@ import javax.persistence.TemporalType;
import org.hibernate.JDBCException; import org.hibernate.JDBCException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.NullOrdering;
import org.hibernate.StaleObjectStateException; import org.hibernate.StaleObjectStateException;
import org.hibernate.boot.TempTableDdlTransactionHandling; import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
@ -34,6 +35,7 @@ import org.hibernate.dialect.sequence.HSQLSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport; import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor; import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor; 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.LocalTemporaryTableStrategy;
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter; import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; 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.internal.SequenceInformationExtractorHSQLDBDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; 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 @Override
public String castPattern(CastType from, CastType to) { public String castPattern(CastType from, CastType to) {
if ( from== BOOLEAN if ( from== BOOLEAN
@ -429,8 +447,8 @@ public class HSQLDialect extends Dialect {
} }
@Override @Override
public boolean supportsUnionAll() { public NullOrdering getNullOrdering() {
return true; return NullOrdering.FIRST;
} }
@Override @Override

View File

@ -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;
}
}

View File

@ -18,6 +18,7 @@ import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.unique.InformixUniqueDelegate; import org.hibernate.dialect.unique.InformixUniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate; import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; 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.TemplatedViolatedConstraintNameExtractor;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor; import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
import org.hibernate.internal.util.JdbcExceptionHelper; 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.LocalTemporaryTableStrategy;
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter; import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; 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.internal.SequenceInformationExtractorInformixDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
@ -159,6 +165,17 @@ public class InformixDialect extends Dialect {
//coalesce() and nullif() both supported since Informix 12 //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 * Informix has no extract() function, but we can
* partially emulate it by using the appropriate * partially emulate it by using the appropriate

View File

@ -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;
}
}

View File

@ -17,6 +17,7 @@ import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.ANSISequenceSupport; import org.hibernate.dialect.sequence.ANSISequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.TemporalUnit; 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.IdTable;
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter; import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; 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.internal.SequenceNameExtractorImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes; 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 @Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) { public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
return "timestampadd(?1, ?2, ?3)"; return "timestampadd(?1, ?2, ?3)";

View File

@ -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;
}
}

View File

@ -6,11 +6,16 @@
*/ */
package org.hibernate.dialect; package org.hibernate.dialect;
import org.hibernate.LockOptions; import org.hibernate.dialect.sequence.MariaDBSequenceSupport;
import org.hibernate.dialect.sequence.ANSISequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.spi.QueryEngine; 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.internal.SequenceInformationExtractorMariaDBDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
@ -25,39 +30,51 @@ public class MariaDBDialect extends MySQLDialect {
private final int version; private final int version;
int getMariaVersion() {
return version;
}
public MariaDBDialect() { public MariaDBDialect() {
this(500); this(500);
} }
public MariaDBDialect(DialectResolutionInfo info) {
this( info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10 );
}
public MariaDBDialect(int version) { public MariaDBDialect(int version) {
super( version < 530 ? 500 : 570 ); super( version < 530 ? 500 : 570 );
this.version = version; this.version = version;
} }
public MariaDBDialect(DialectResolutionInfo info) { @Override
this( info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10 ); public int getVersion() {
return version;
} }
@Override @Override
public void initializeFunctionRegistry(QueryEngine queryEngine) { public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry(queryEngine); super.initializeFunctionRegistry(queryEngine);
if ( getMariaVersion() >= 1020 ) { if ( getVersion() >= 1020 ) {
queryEngine.getSqmFunctionRegistry().registerNamed("json_valid", StandardBasicTypes.NUMERIC_BOOLEAN); 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() { public boolean supportsRowValueConstructorSyntaxInInList() {
return true; return true;
} }
@Override @Override
public boolean supportsColumnCheck() { public boolean supportsColumnCheck() {
return getMariaVersion() >= 1020; return getVersion() >= 1020;
} }
@Override @Override
@ -67,14 +84,14 @@ public class MariaDBDialect extends MySQLDialect {
@Override @Override
public boolean supportsIfExistsBeforeConstraintName() { public boolean supportsIfExistsBeforeConstraintName() {
return getMariaVersion() >= 1000; return getVersion() >= 1000;
} }
@Override @Override
public SequenceSupport getSequenceSupport() { public SequenceSupport getSequenceSupport() {
return getMariaVersion() < 1030 return getVersion() < 1030
? super.getSequenceSupport() ? super.getSequenceSupport()
: ANSISequenceSupport.INSTANCE; : MariaDBSequenceSupport.INSTANCE;
} }
@Override @Override

View File

@ -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;
}
}

View File

@ -9,8 +9,11 @@ package org.hibernate.dialect;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.CommonFunctionFactory; import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitOffsetLimitHandler;
import org.hibernate.dialect.sequence.MaxDBSequenceSupport; import org.hibernate.dialect.sequence.MaxDBSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.TrimSpec; 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.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.CaseFragment; import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DecodeCaseFragment; 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.internal.SequenceInformationExtractorSAPDBDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
@ -60,6 +68,11 @@ public class MaxDBDialect extends Dialect {
return 0; return 0;
} }
@Override
public LimitHandler getLimitHandler() {
return LimitOffsetLimitHandler.INSTANCE;
}
@Override @Override
public void initializeFunctionRegistry(QueryEngine queryEngine) { public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry( queryEngine ); super.initializeFunctionRegistry( queryEngine );
@ -112,6 +125,17 @@ public class MaxDBDialect extends Dialect {
).setArgumentListSignature("(pattern, string[, start])"); ).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 @Override
public String trimPattern(TrimSpec specification, char character) { public String trimPattern(TrimSpec specification, char character) {
return AbstractTransactSQLDialect.replaceLtrimRtrim(specification, character); return AbstractTransactSQLDialect.replaceLtrimRtrim(specification, character);

View File

@ -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
}
}

View File

@ -15,10 +15,16 @@ import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
import org.hibernate.dialect.sequence.MimerSequenceSupport; import org.hibernate.dialect.sequence.MimerSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.CastType; import org.hibernate.query.CastType;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine; 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.internal.SequenceInformationExtractorMimerSQLDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
@ -107,6 +113,17 @@ public class MimerSQLDialect extends Dialect {
CommonFunctionFactory.localtimeLocaltimestamp( queryEngine ); 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} * Mimer does have a real {@link java.sql.Types#BOOLEAN}
* type, but it doesn't know how to cast to it. * type, but it doesn't know how to cast to it.

View File

@ -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
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.dialect; package org.hibernate.dialect;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.NullOrdering;
import org.hibernate.NullPrecedence; import org.hibernate.NullPrecedence;
import org.hibernate.PessimisticLockException; import org.hibernate.PessimisticLockException;
import org.hibernate.boot.TempTableDdlTransactionHandling; 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.MySQLUniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate; import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.exception.LockTimeoutException; import org.hibernate.exception.LockTimeoutException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate; 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.LocalTemporaryTableStrategy;
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter; import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; 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 org.hibernate.type.StandardBasicTypes;
import java.sql.CallableStatement; import java.sql.CallableStatement;
@ -59,8 +66,8 @@ import static org.hibernate.query.CastType.BOOLEAN;
public class MySQLDialect extends Dialect { public class MySQLDialect extends Dialect {
private final UniqueDelegate uniqueDelegate; private final UniqueDelegate uniqueDelegate;
private MySQLStorageEngine storageEngine; private final MySQLStorageEngine storageEngine;
private int version; private final int version;
public MySQLDialect(DialectResolutionInfo info) { public MySQLDialect(DialectResolutionInfo info) {
this( info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10 ); this( info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10 );
@ -95,7 +102,7 @@ public class MySQLDialect extends Dialect {
registerColumnType( Types.NUMERIC, "decimal($p,$s)" ); //it's just a synonym registerColumnType( Types.NUMERIC, "decimal($p,$s)" ); //it's just a synonym
if ( getVersion() < 570) { if ( getMySQLVersion() < 570) {
registerColumnType( Types.TIMESTAMP, "datetime" ); registerColumnType( Types.TIMESTAMP, "datetime" );
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp" ); registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp" );
} }
@ -107,7 +114,7 @@ public class MySQLDialect extends Dialect {
} }
// max length for VARCHAR changed in 5.0.3 // 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.VARCHAR, maxVarcharLen, "varchar($l)" );
registerColumnType( Types.VARBINARY, maxVarcharLen, "varbinary($l)" ); registerColumnType( Types.VARBINARY, maxVarcharLen, "varbinary($l)" );
@ -144,7 +151,7 @@ public class MySQLDialect extends Dialect {
registerColumnType( Types.NCLOB, maxLobLen, "text" ); registerColumnType( Types.NCLOB, maxLobLen, "text" );
registerColumnType( Types.NCLOB, maxTinyLobLen, "tinytext" ); registerColumnType( Types.NCLOB, maxTinyLobLen, "tinytext" );
if ( getVersion() >= 570) { if ( getMySQLVersion() >= 570) {
// MySQL 5.7 brings JSON native support with a dedicated datatype // MySQL 5.7 brings JSON native support with a dedicated datatype
// https://dev.mysql.com/doc/refman/5.7/en/json.html // https://dev.mysql.com/doc/refman/5.7/en/json.html
registerColumnType(Types.JAVA_OBJECT, "json"); registerColumnType(Types.JAVA_OBJECT, "json");
@ -163,6 +170,10 @@ public class MySQLDialect extends Dialect {
return version; return version;
} }
public int getMySQLVersion() {
return version;
}
@Override @Override
public long getDefaultLobLength() { public long getDefaultLobLength() {
//max length for mediumblob or mediumtext //max length for mediumblob or mediumtext
@ -237,7 +248,7 @@ public class MySQLDialect extends Dialect {
CommonFunctionFactory.format_dateFormat( queryEngine ); CommonFunctionFactory.format_dateFormat( queryEngine );
CommonFunctionFactory.makedateMaketime( queryEngine ); CommonFunctionFactory.makedateMaketime( queryEngine );
if ( getVersion() < 570 ) { if ( getMySQLVersion() < 570 ) {
CommonFunctionFactory.sysdateParens( queryEngine ); CommonFunctionFactory.sysdateParens( queryEngine );
} }
else { 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) { private void time(QueryEngine queryEngine) {
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "time" ) queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder( "time" )
.setExactArgumentCount( 1 ) .setExactArgumentCount( 1 )
@ -266,7 +288,7 @@ public class MySQLDialect extends Dialect {
*/ */
@Override @Override
public String currentTimestamp() { 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 @Override
public boolean supportsRowValueConstructorSyntaxInInList() { public boolean supportsRowValueConstructorSyntaxInInList() {
return getVersion() >= 570; return getMySQLVersion() >= 570;
} }
@Override @Override
public boolean supportsUnionAll() { public boolean supportsUnionAll() {
return getVersion() >= 500; return getMySQLVersion() >= 500;
} }
@Override @Override
@ -382,7 +404,7 @@ public class MySQLDialect extends Dialect {
@Override @Override
public String getQueryHintString(String query, String hints) { public String getQueryHintString(String query, String hints) {
return getVersion() < 500 return getMySQLVersion() < 500
? super.getQueryHintString( query, hints ) ? super.getQueryHintString( query, hints )
: IndexQueryHintHandler.INSTANCE.addQueryHints( query, hints ); : IndexQueryHintHandler.INSTANCE.addQueryHints( query, hints );
} }
@ -396,7 +418,7 @@ public class MySQLDialect extends Dialect {
} }
public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() { public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() {
return getVersion() < 500 ? super.getViolatedConstraintNameExtractor() : EXTRACTOR; return getMySQLVersion() < 500 ? super.getViolatedConstraintNameExtractor() : EXTRACTOR;
} }
private static final ViolatedConstraintNameExtractor EXTRACTOR = private static final ViolatedConstraintNameExtractor EXTRACTOR =
@ -508,6 +530,11 @@ public class MySQLDialect extends Dialect {
return " comment '" + comment + "'"; return " comment '" + comment + "'";
} }
@Override
public NullOrdering getNullOrdering() {
return NullOrdering.SMALLEST;
}
@Override @Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy( public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor, EntityMappingType rootEntityDescriptor,
@ -723,7 +750,7 @@ public class MySQLDialect extends Dialect {
@Override @Override
public String getTableTypeString() { public String getTableTypeString() {
String engineKeyword = getVersion() < 500 ? "type" : "engine"; String engineKeyword = getMySQLVersion() < 500 ? "type" : "engine";
return storageEngine.getTableTypeString( engineKeyword ); return storageEngine.getTableTypeString( engineKeyword );
} }
@ -738,7 +765,7 @@ public class MySQLDialect extends Dialect {
} }
protected MySQLStorageEngine getDefaultMySQLStorageEngine() { protected MySQLStorageEngine getDefaultMySQLStorageEngine() {
return getVersion() < 550 ? MyISAMStorageEngine.INSTANCE : InnoDBStorageEngine.INSTANCE; return getMySQLVersion() < 550 ? MyISAMStorageEngine.INSTANCE : InnoDBStorageEngine.INSTANCE;
} }
@Override @Override
@ -900,12 +927,12 @@ public class MySQLDialect extends Dialect {
@Override @Override
public boolean supportsSkipLocked() { public boolean supportsSkipLocked() {
return getVersion() >= 800; return getMySQLVersion() >= 800;
} }
@Override @Override
public boolean supportsNoWait() { public boolean supportsNoWait() {
return getVersion() >= 800; return getMySQLVersion() >= 800;
} }
public boolean supportsWait() { public boolean supportsWait() {
@ -914,11 +941,11 @@ public class MySQLDialect extends Dialect {
} }
boolean supportsForShare() { boolean supportsForShare() {
return getVersion() >= 800; return getMySQLVersion() >= 800;
} }
boolean supportsAliasLocks() { boolean supportsAliasLocks() {
return getVersion() >= 800; return getMySQLVersion() >= 800;
} }
@Override @Override

View File

@ -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;
}
}

View File

@ -22,6 +22,7 @@ import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters; import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.exception.LockTimeoutException; 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.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.*; 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.internal.SequenceInformationExtractorOracleDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
@ -179,6 +185,17 @@ public class OracleDialect extends Dialect {
).setArgumentListSignature("(pattern, string[, start])"); ).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 @Override
public String currentDate() { public String currentDate() {
return getVersion() < 9 ? currentTimestamp() : "current_date"; return getVersion() < 9 ? currentTimestamp() : "current_date";
@ -783,11 +800,6 @@ public class OracleDialect extends Dialect {
return (ResultSet) ps.getObject( 1 ); return (ResultSet) ps.getObject( 1 );
} }
@Override
public boolean supportsUnionAll() {
return true;
}
@Override @Override
public boolean supportsCommentOn() { public boolean supportsCommentOn() {
return true; return true;

View File

@ -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;
}
}

View File

@ -9,7 +9,6 @@ package org.hibernate.dialect;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.PessimisticLockException; import org.hibernate.PessimisticLockException;
import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.TypeContributions;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.CommonFunctionFactory; 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.PostgreSQLSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.LockAcquisitionException; import org.hibernate.exception.LockAcquisitionException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor; 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.SemanticException;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction; import org.hibernate.query.sqm.mutation.internal.cte.CteStrategy;
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.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.service.ServiceRegistry; 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.StandardBasicTypes;
import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.ValueExtractor;
@ -460,11 +462,6 @@ public class PostgreSQLDialect extends Dialect {
return false; return false;
} }
@Override
public boolean supportsUnionAll() {
return true;
}
/** /**
* Workaround for postgres bug #1453 * Workaround for postgres bug #1453
* <p/> * <p/>
@ -505,26 +502,22 @@ public class PostgreSQLDialect extends Dialect {
return String.valueOf( bool ); return String.valueOf( bool );
} }
@Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy( public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor, EntityMappingType rootEntityDescriptor,
RuntimeModelCreationContext runtimeModelCreationContext) { RuntimeModelCreationContext runtimeModelCreationContext) {
return new LocalTemporaryTableStrategy( return new CteStrategy( rootEntityDescriptor, runtimeModelCreationContext );
new IdTable( rootEntityDescriptor, base -> "HT_" + base, this ),
() -> new TempIdTableExporter( true, this::getTypeName ) {
@Override
protected String getCreateCommand() {
return "create temporary table";
} }
@Override @Override
protected String getCreateOptions() { public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
return "on commit drop"; return new StandardSqlAstTranslatorFactory() {
@Override
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
SessionFactoryImplementor sessionFactory, Statement statement) {
return new PostgreSQLSqlAstTranslator<>( sessionFactory, statement );
} }
}, };
AfterUseAction.CLEAN,
TempTableDdlTransactionHandling.NONE,
runtimeModelCreationContext.getSessionFactory()
);
} }
@Override @Override

View File

@ -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;
}
}

View File

@ -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
}
}

View File

@ -13,6 +13,7 @@ import org.hibernate.dialect.pagination.FetchLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.RDMSSequenceSupport; import org.hibernate.dialect.sequence.RDMSSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.entity.Lockable; import org.hibernate.persister.entity.Lockable;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
@ -20,6 +21,12 @@ import org.hibernate.query.TrimSpec;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.CaseFragment; import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DecodeCaseFragment; 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 org.jboss.logging.Logger;
import java.sql.Types; import java.sql.Types;
@ -151,6 +158,17 @@ public class RDMSOS2200Dialect extends Dialect {
CommonFunctionFactory.monthsBetween( queryEngine ); 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 @Override
public long getFractionalSecondPrecisionInNanos() { public long getFractionalSecondPrecisionInNanos() {
return 1_000; //microseconds return 1_000; //microseconds
@ -290,12 +308,6 @@ public class RDMSOS2200Dialect extends Dialect {
return FetchLimitHandler.INSTANCE; return FetchLimitHandler.INSTANCE;
} }
@Override
public boolean supportsUnionAll() {
// RDMS supports the UNION ALL clause.
return true;
}
@Override @Override
public String getFromDual() { public String getFromDual() {
return "from rdms.rdms_dummy where key_col = 1"; return "from rdms.rdms_dummy where key_col = 1";

View File

@ -18,11 +18,17 @@ import org.hibernate.dialect.sequence.ANSISequenceSupport;
import org.hibernate.dialect.sequence.NoSequenceSupport; import org.hibernate.dialect.sequence.NoSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.LockTimeoutException; import org.hibernate.exception.LockTimeoutException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine; 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.StandardBasicTypes;
import org.hibernate.type.descriptor.sql.SmallIntTypeDescriptor; import org.hibernate.type.descriptor.sql.SmallIntTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
@ -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 @Override
public String currentTimestamp() { public String currentTimestamp() {
return "sysdatetime()"; return "sysdatetime()";

View File

@ -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;
}
}

View File

@ -19,6 +19,7 @@ import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitOffsetLimitHandler; import org.hibernate.dialect.pagination.LimitOffsetLimitHandler;
import org.hibernate.dialect.unique.UniqueDelegate; import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver; import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.mapping.Column; import org.hibernate.mapping.Column;
@ -31,6 +32,11 @@ import org.hibernate.persister.entity.Lockable;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine; 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.tool.schema.spi.Exporter;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
@ -377,6 +383,17 @@ public class SpannerDialect extends Dialect {
.register(); .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 @Override
public Exporter<Table> getTableExporter() { public Exporter<Table> getTableExporter() {
return this.spannerTableExporter; return this.spannerTableExporter;
@ -404,11 +421,6 @@ public class SpannerDialect extends Dialect {
return String.valueOf( bool ); return String.valueOf( bool );
} }
@Override
public boolean supportsUnionAll() {
return true;
}
@Override @Override
public String translateExtractField(TemporalUnit unit) { public String translateExtractField(TemporalUnit unit) {
switch (unit) { switch (unit) {
@ -769,7 +781,7 @@ public class SpannerDialect extends Dialect {
@Override @Override
public LimitHandler getLimitHandler() { public LimitHandler getLimitHandler() {
return new LimitOffsetLimitHandler(); return LimitOffsetLimitHandler.INSTANCE;
} }
/* Type conversion and casting */ /* Type conversion and casting */

View File

@ -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
}
}

View File

@ -10,6 +10,7 @@ import org.hibernate.LockOptions;
import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.TopLimitHandler; import org.hibernate.dialect.pagination.TopLimitHandler;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.exception.LockTimeoutException; import org.hibernate.exception.LockTimeoutException;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
@ -18,6 +19,11 @@ import org.hibernate.query.TrimSpec;
import org.hibernate.sql.ForUpdateFragment; import org.hibernate.sql.ForUpdateFragment;
import org.hibernate.sql.JoinFragment; import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.Sybase11JoinFragment; 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.SqlTypeDescriptor;
import org.hibernate.type.descriptor.sql.TinyIntTypeDescriptor; import org.hibernate.type.descriptor.sql.TinyIntTypeDescriptor;
@ -70,6 +76,17 @@ public class SybaseASEDialect extends SybaseDialect {
registerSybaseKeywords(); 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 * The Sybase ASE {@code BIT} type does not allow
* null values, so we don't use it. * null values, so we don't use it.

View File

@ -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;
}
}

View File

@ -12,6 +12,12 @@ import org.hibernate.dialect.identity.SybaseAnywhereIdentityColumnSupport;
import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.TopLimitHandler; import org.hibernate.dialect.pagination.TopLimitHandler;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; 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.BitTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
@ -56,6 +62,17 @@ public class SybaseAnywhereDialect extends SybaseDialect {
registerColumnType( Types.VARBINARY, "long binary)" ); 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 @Override
public boolean supportsTimezoneTypes() { public boolean supportsTimezoneTypes() {
return true; return true;

View File

@ -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
}
}

View File

@ -8,8 +8,14 @@ package org.hibernate.dialect;
import org.hibernate.dialect.function.CommonFunctionFactory; import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.TemporalUnit; import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine; 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.BlobTypeDescriptor;
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor; import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
@ -45,6 +51,17 @@ public class SybaseDialect extends AbstractTransactSQLDialect {
registerColumnType( Types.BIGINT, "numeric(19,0)" ); 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 @Override
public int getVersion() { public int getVersion() {
return version; return version;

View File

@ -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;
}
}

View File

@ -19,6 +19,7 @@ import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.TopLimitHandler; import org.hibernate.dialect.pagination.TopLimitHandler;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; 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.TemplatedViolatedConstraintNameExtractor;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor; import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
import org.hibernate.mapping.Column; 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.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.ForUpdateFragment; 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.internal.StandardIndexExporter;
import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.tool.schema.spi.Exporter;
import org.hibernate.type.StandardBasicTypes; 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 @Override
public int getVersion() { public int getVersion() {
return version; return version;

View File

@ -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
}
}

View File

@ -14,6 +14,7 @@ import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.TimesTenLimitHandler; import org.hibernate.dialect.pagination.TimesTenLimitHandler;
import org.hibernate.dialect.sequence.SequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.sequence.TimesTenSequenceSupport; import org.hibernate.dialect.sequence.TimesTenSequenceSupport;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.Lockable; 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.IdTable;
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter; import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; 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.internal.SequenceInformationExtractorTimesTenDatabaseImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
@ -129,6 +135,17 @@ public class TimesTenDialect extends Dialect {
).setArgumentListSignature("(pattern, string[, start])"); ).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 @Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) { public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
switch (unit) { switch (unit) {
@ -262,11 +279,6 @@ public class TimesTenDialect extends Dialect {
} }
} }
@Override
public boolean supportsUnionAll() {
return true;
}
@Override @Override
public boolean supportsCircularCascadeDeleteConstraints() { public boolean supportsCircularCascadeDeleteConstraints() {
return false; return false;

View File

@ -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
}
}

View File

@ -101,6 +101,7 @@ public final class TypeNames {
* the default type name otherwise * the default type name otherwise
*/ */
public String get(int typeCode, Long size, Integer precision, Integer scale) { public String get(int typeCode, Long size, Integer precision, Integer scale) {
if ( size != null ) {
final Map<Long, String> map = weighted.get( typeCode ); final Map<Long, String> map = weighted.get( typeCode );
if ( map != null && map.size() > 0 ) { if ( map != null && map.size() > 0 ) {
// iterate entries ordered by capacity to find first fit // iterate entries ordered by capacity to find first fit
@ -110,6 +111,7 @@ public final class TypeNames {
} }
} }
} }
}
// if we get here one of 2 things happened: // if we get here one of 2 things happened:
// 1) There was no weighted registration for that typeCode // 1) There was no weighted registration for that typeCode

View File

@ -12,6 +12,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.hibernate.engine.spi.RowSelection; 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.CASE_INSENSITIVE;
import static java.util.regex.Pattern.compile; import static java.util.regex.Pattern.compile;
@ -270,6 +271,143 @@ public abstract class AbstractLimitHandler implements LimitHandler {
return convertToFirstRowValue( selection.getFirstRow() ); 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 * Insert a fragment of SQL right after
* {@code SELECT}, but before {@code DISTINCT} * {@code SELECT}, but before {@code DISTINCT}

View File

@ -7,6 +7,7 @@
package org.hibernate.dialect.pagination; package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
import static java.lang.String.valueOf; import static java.lang.String.valueOf;
@ -39,8 +40,21 @@ public abstract class AbstractNoOffsetLimitHandler extends AbstractLimitHandler
} }
String limitClause = limitClause(); String limitClause = limitClause();
if ( !supportsVariableLimit() ) { if ( !supportsVariableLimit() ) {
String limit = valueOf( getMaxOrLimit(selection) ); String limitLiteral = valueOf( getMaxOrLimit(selection) );
limitClause = limitClause.replace( "?", limit ); 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 ); return insert( limitClause, sql );
} }

View File

@ -7,6 +7,7 @@
package org.hibernate.dialect.pagination; package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
/** /**
* Superclass for simple {@link LimitHandler}s that don't * Superclass for simple {@link LimitHandler}s that don't
@ -26,6 +27,14 @@ public abstract class AbstractSimpleLimitHandler extends AbstractLimitHandler {
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) { protected String insert(String limitClause, String sql) {
return insertBeforeForUpdate( limitClause, sql ); return insertBeforeForUpdate( limitClause, sql );
} }

View File

@ -7,6 +7,7 @@
package org.hibernate.dialect.pagination; package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
/** /**
* A {@link LimitHandler} for DB2. Uses {@code FETCH FIRST n ROWS ONLY}, * A {@link LimitHandler} for DB2. Uses {@code FETCH FIRST n ROWS ONLY},
@ -34,8 +35,29 @@ public class LegacyDB2LimitHandler extends AbstractLimitHandler {
} }
} }
private String fetchFirstRows(RowSelection selection) { private String fetchFirstRows(RowSelection limit) {
return " fetch first " + getMaxOrLimit( selection ) + " rows only"; 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 @Override

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.pagination;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
/** /**
* Stub {@link LimitHandler} that delegates all operations * Stub {@link LimitHandler} that delegates all operations
@ -81,4 +82,20 @@ public class LegacyLimitHandler extends AbstractLimitHandler {
getMaxOrLimit( selection ) 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 )
);
}
} }

View File

@ -7,6 +7,7 @@
package org.hibernate.dialect.pagination; package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -56,6 +57,41 @@ public class LegacyOracleLimitHandler extends AbstractLimitHandler {
return pagingSelect.toString(); 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 @Override
public boolean supportsLimit() { public boolean supportsLimit() {
return true; return true;

View File

@ -10,6 +10,8 @@ import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import org.hibernate.engine.spi.RowSelection; 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. * Contract defining dialect-specific limit and offset handling.
@ -40,6 +42,58 @@ public interface LimitHandler {
*/ */
boolean supportsLimitOffset(); 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. * Return processed SQL query.
* *
@ -47,7 +101,9 @@ public interface LimitHandler {
* @param selection the selection criteria for rows. * @param selection the selection criteria for rows.
* *
* @return Query statement with LIMIT clause applied. * @return Query statement with LIMIT clause applied.
* @deprecated todo (6.0): remove in favor of Limit version?
*/ */
@Deprecated
String processSql(String sql, RowSelection selection); String processSql(String sql, RowSelection selection);
/** /**
@ -60,7 +116,9 @@ public interface LimitHandler {
* @param index Index from which to start binding. * @param index Index from which to start binding.
* @return The number of parameter values bound. * @return The number of parameter values bound.
* @throws SQLException Indicates problems binding parameter values. * @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) int bindLimitParametersAtStartOfQuery(RowSelection selection, PreparedStatement statement, int index)
throws SQLException; throws SQLException;
@ -74,7 +132,9 @@ public interface LimitHandler {
* @param index Index from which to start binding. * @param index Index from which to start binding.
* @return The number of parameter values bound. * @return The number of parameter values bound.
* @throws SQLException Indicates problems binding parameter values. * @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) int bindLimitParametersAtEndOfQuery(RowSelection selection, PreparedStatement statement, int index)
throws SQLException; throws SQLException;
@ -86,6 +146,8 @@ public interface LimitHandler {
* @param selection the selection criteria for rows. * @param selection the selection criteria for rows.
* @param statement Statement which number of returned rows shall be limited. * @param statement Statement which number of returned rows shall be limited.
* @throws SQLException Indicates problems while limiting maximum rows returned. * @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; void setMaxRows(RowSelection selection, PreparedStatement statement) throws SQLException;
} }

View File

@ -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 );
}
}
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.dialect.pagination; package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
/** /**
* A {@link LimitHandler} for databases which support the * A {@link LimitHandler} for databases which support the
@ -71,6 +72,52 @@ public class OffsetFetchLimitHandler extends AbstractLimitHandler {
return insert( offsetFetch.toString(), sql ); 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) {} void begin(String sql, StringBuilder offsetFetch, boolean hasFirstRow, boolean hasMaxRows) {}
String insert(String offsetFetch, String sql) { String insert(String offsetFetch, String sql) {

View File

@ -15,6 +15,7 @@ import java.util.regex.Pattern;
import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.RowSelection;
import org.hibernate.internal.util.StringHelper; 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.CASE_INSENSITIVE;
import static java.util.regex.Pattern.compile; import static java.util.regex.Pattern.compile;
@ -132,6 +133,84 @@ public class SQLServer2005LimitHandler extends AbstractLimitHandler {
: 0; : 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 * 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 * comma-separated list of all aliases in the list, unless the given list

View File

@ -52,7 +52,8 @@ public class SQLServer2012LimitHandler extends OffsetFetchLimitHandler {
//if we can find the end of the select //if we can find the end of the select
//clause, we will add a dummy column to //clause, we will add a dummy column to
//it below, so order by that column //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 { else {
//otherwise order by the first column //otherwise order by the first column
@ -66,22 +67,4 @@ public class SQLServer2012LimitHandler extends OffsetFetchLimitHandler {
offsetFetch.append(" offset 0 rows"); 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;
}
} }

View File

@ -7,6 +7,7 @@
package org.hibernate.dialect.pagination; package org.hibernate.dialect.pagination;
import org.hibernate.engine.spi.RowSelection; import org.hibernate.engine.spi.RowSelection;
import org.hibernate.query.Limit;
/** /**
* A {@link LimitHandler} for Informix which supports the syntax * A {@link LimitHandler} for Informix which supports the syntax
@ -56,6 +57,40 @@ public class SkipFirstLimitHandler extends AbstractLimitHandler {
return insertAfterSelect( sql, skipFirst.toString() ); 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 @Override
public final boolean supportsLimit() { public final boolean supportsLimit() {
return true; return true;

View File

@ -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;
}
}

View File

@ -10,7 +10,9 @@ package org.hibernate.engine.spi;
* Represents a selection criteria for rows in a JDBC {@link java.sql.ResultSet} * Represents a selection criteria for rows in a JDBC {@link java.sql.ResultSet}
* *
* @author Gavin King * @author Gavin King
* @deprecated todo (6.0): remove in favor of Limit within QueryOptions?
*/ */
@Deprecated
public final class RowSelection { public final class RowSelection {
private Integer firstRow; private Integer firstRow;
private Integer maxRows; private Integer maxRows;

View File

@ -275,6 +275,18 @@ public final class CollectionHelper {
return objects == null || objects.length == 0; 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) { public static <T> Set<T> setOf(T... values) {
final HashSet<T> set = new HashSet<>( determineProperSizing( values.length ) ); final HashSet<T> set = new HashSet<>( determineProperSizing( values.length ) );
Collections.addAll( set, values ); Collections.addAll( set, values );

View File

@ -99,11 +99,10 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
sessionFactory sessionFactory
); );
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlSelect );
final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() ); final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
applyNaturalIdAsJdbcParameters( bindValue, jdbcParameters, jdbcParamBindings, session ); applyNaturalIdAsJdbcParameters( bindValue, jdbcParameters, jdbcParamBindings, session );
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
.translate( jdbcParamBindings, QueryOptions.NONE );
//noinspection unchecked //noinspection unchecked
final List<T> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list( final List<T> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
@ -179,8 +178,6 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
sessionFactory sessionFactory
); );
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlSelect );
final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() ); final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
applyNaturalIdAsJdbcParameters( applyNaturalIdAsJdbcParameters(
bindValue, bindValue,
@ -188,6 +185,8 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
jdbcParamBindings, jdbcParamBindings,
session session
); );
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
.translate( jdbcParamBindings, QueryOptions.NONE );
final List<?> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list( final List<?> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
jdbcSelect, jdbcSelect,
@ -252,10 +251,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlSelect );
final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() ); final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
int offset = jdbcParamBindings.registerParametersForEachJdbcValue( int offset = jdbcParamBindings.registerParametersForEachJdbcValue(
id, id,
Clause.WHERE, Clause.WHERE,
@ -264,6 +260,8 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
session session
); );
assert offset == jdbcParameters.size(); assert offset == jdbcParameters.size();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
.translate( jdbcParamBindings, QueryOptions.NONE );
final List<Object[]> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list( final List<Object[]> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
jdbcSelect, jdbcSelect,

View File

@ -7,7 +7,6 @@
package org.hibernate.loader.ast.internal; package org.hibernate.loader.ast.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.LockOptions; 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.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement; 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.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
@ -116,11 +114,7 @@ public class CollectionElementLoaderByIndex implements Loader {
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory )
.translate( sqlAst );
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( keyJdbcCount ); final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( keyJdbcCount );
jdbcSelect.bindFilterJdbcParameters( jdbcParameterBindings );
int offset = jdbcParameterBindings.registerParametersForEachJdbcValue( int offset = jdbcParameterBindings.registerParametersForEachJdbcValue(
key, key,
@ -138,6 +132,8 @@ public class CollectionElementLoaderByIndex implements Loader {
session session
); );
assert offset == jdbcParameters.size(); assert offset == jdbcParameters.size();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
.translate( jdbcParameterBindings, QueryOptions.NONE );
List<Object> list = jdbcServices.getJdbcSelectExecutor().list( List<Object> list = jdbcServices.getJdbcSelectExecutor().list(
jdbcSelect, jdbcSelect,

View File

@ -7,7 +7,6 @@
package org.hibernate.loader.ast.internal; package org.hibernate.loader.ast.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.LockOptions; 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.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement; 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.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
@ -159,7 +157,8 @@ public class CollectionLoaderBatchKey implements CollectionLoader {
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); 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 ); final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( keyJdbcCount * smallBatchLength );
jdbcSelect.bindFilterJdbcParameters( jdbcParameterBindings ); jdbcSelect.bindFilterJdbcParameters( jdbcParameterBindings );

View File

@ -7,7 +7,6 @@
package org.hibernate.loader.ast.internal; package org.hibernate.loader.ast.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.LockOptions; 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.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement; 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.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
@ -95,11 +93,7 @@ public class CollectionLoaderSingleKey implements CollectionLoader {
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( keyJdbcCount ); final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( keyJdbcCount );
jdbcSelect.bindFilterJdbcParameters( jdbcParameterBindings );
int offset = jdbcParameterBindings.registerParametersForEachJdbcValue( int offset = jdbcParameterBindings.registerParametersForEachJdbcValue(
key, key,
Clause.WHERE, Clause.WHERE,
@ -108,6 +102,8 @@ public class CollectionLoaderSingleKey implements CollectionLoader {
session session
); );
assert offset == jdbcParameters.size(); assert offset == jdbcParameters.size();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
.translate( jdbcParameterBindings, QueryOptions.NONE );
jdbcServices.getJdbcSelectExecutor().list( jdbcServices.getJdbcSelectExecutor().list(
jdbcSelect, jdbcSelect,

View File

@ -68,7 +68,8 @@ public class CollectionLoaderSubSelectFetch implements CollectionLoader {
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); 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( jdbcServices.getJdbcSelectExecutor().list(
jdbcSelect, jdbcSelect,

View File

@ -7,7 +7,6 @@
package org.hibernate.loader.ast.internal; package org.hibernate.loader.ast.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.LockMode; 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.predicate.ComparisonPredicate;
import org.hibernate.sql.ast.tree.select.QuerySpec; import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SelectStatement; 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.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.internal.JdbcParameterImpl; import org.hibernate.sql.exec.internal.JdbcParameterImpl;
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl; import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
@ -185,7 +183,8 @@ class DatabaseSnapshotExecutor {
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); 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) { Object[] loadDatabaseSnapshot(Object id, SharedSessionContractImplementor session) {

View File

@ -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.InListPredicate;
import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate; import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate;
import org.hibernate.sql.ast.tree.predicate.Predicate; 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.QuerySpec;
import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.exec.internal.JdbcParameterImpl; import org.hibernate.sql.exec.internal.JdbcParameterImpl;
@ -882,7 +883,7 @@ public class LoaderSelectBuilder {
); );
} }
private QuerySpec generateSubSelect( private QueryPart generateSubSelect(
PluralAttributeMapping attributeMapping, PluralAttributeMapping attributeMapping,
TableGroup rootTableGroup, TableGroup rootTableGroup,
SubselectFetch subselect, SubselectFetch subselect,

View File

@ -25,7 +25,7 @@ import org.hibernate.query.NavigablePath;
import org.hibernate.query.ResultListTransformer; import org.hibernate.query.ResultListTransformer;
import org.hibernate.query.TupleTransformer; import org.hibernate.query.TupleTransformer;
import org.hibernate.query.spi.QueryOptions; 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.Clause;
import org.hibernate.sql.ast.spi.FromClauseAccess; import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator; 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.SqlAstProcessingState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver; import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.from.TableGroup; 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.ast.tree.select.QuerySpec;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
@ -49,11 +50,10 @@ public class LoaderSqlAstCreationState
List<Fetch> visitFetches(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState); List<Fetch> visitFetches(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState);
} }
private final QuerySpec querySpec;
private final SqlAliasBaseManager sqlAliasBaseManager; private final SqlAliasBaseManager sqlAliasBaseManager;
private final boolean forceIdentifierSelection; private final boolean forceIdentifierSelection;
private final SqlAstCreationContext sf; private final SqlAstCreationContext sf;
private final SqlAstQuerySpecProcessingStateImpl processingState; private final SqlAstQueryPartProcessingStateImpl processingState;
private final FromClauseAccess fromClauseAccess; private final FromClauseAccess fromClauseAccess;
private final LockOptions lockOptions; private final LockOptions lockOptions;
private final FetchProcessor fetchProcessor; private final FetchProcessor fetchProcessor;
@ -61,22 +61,21 @@ public class LoaderSqlAstCreationState
private Set<AssociationKey> visitedAssociationKeys = new HashSet<>(); private Set<AssociationKey> visitedAssociationKeys = new HashSet<>();
public LoaderSqlAstCreationState( public LoaderSqlAstCreationState(
QuerySpec querySpec, QueryPart queryPart,
SqlAliasBaseManager sqlAliasBaseManager, SqlAliasBaseManager sqlAliasBaseManager,
FromClauseAccess fromClauseAccess, FromClauseAccess fromClauseAccess,
LockOptions lockOptions, LockOptions lockOptions,
FetchProcessor fetchProcessor, FetchProcessor fetchProcessor,
boolean forceIdentifierSelection, boolean forceIdentifierSelection,
SqlAstCreationContext sf) { SqlAstCreationContext sf) {
this.querySpec = querySpec;
this.sqlAliasBaseManager = sqlAliasBaseManager; this.sqlAliasBaseManager = sqlAliasBaseManager;
this.fromClauseAccess = fromClauseAccess; this.fromClauseAccess = fromClauseAccess;
this.lockOptions = lockOptions; this.lockOptions = lockOptions;
this.fetchProcessor = fetchProcessor; this.fetchProcessor = fetchProcessor;
this.forceIdentifierSelection = forceIdentifierSelection; this.forceIdentifierSelection = forceIdentifierSelection;
this.sf = sf; this.sf = sf;
processingState = new SqlAstQuerySpecProcessingStateImpl( this.processingState = new SqlAstQueryPartProcessingStateImpl(
querySpec, queryPart,
this, this,
this, this,
() -> Clause.IRRELEVANT () -> Clause.IRRELEVANT
@ -99,10 +98,6 @@ public class LoaderSqlAstCreationState
); );
} }
public QuerySpec getQuerySpec() {
return querySpec;
}
@Override @Override
public SqlAstCreationContext getCreationContext() { public SqlAstCreationContext getCreationContext() {
return sf; return sf;
@ -135,7 +130,7 @@ public class LoaderSqlAstCreationState
@Override @Override
public List<Fetch> visitFetches(FetchParent fetchParent) { public List<Fetch> visitFetches(FetchParent fetchParent) {
return fetchProcessor.visitFetches( fetchParent, getQuerySpec(), this ); return fetchProcessor.visitFetches( fetchParent, processingState.getInflightQueryPart().getFirstQuerySpec(), this );
} }
@Override @Override

View File

@ -9,7 +9,6 @@ package org.hibernate.loader.ast.internal;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.LockMode; 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.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement; 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.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl; import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.Callback;
@ -255,8 +253,6 @@ public class MultiIdLoaderStandard<T> implements MultiIdEntityLoader<T> {
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() ); final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
int offset = 0; 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) // we should have used all of the JdbcParameter references (created bindings for all)
assert offset == jdbcParameters.size(); assert offset == jdbcParameters.size();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
.translate( jdbcParameterBindings, QueryOptions.NONE );
final LoadingEntityCollector loadingEntityCollector; final LoadingEntityCollector loadingEntityCollector;

View File

@ -7,7 +7,6 @@
package org.hibernate.loader.ast.internal; package org.hibernate.loader.ast.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
@ -19,17 +18,14 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.loader.ast.spi.MultiNaturalIdLoadOptions; import org.hibernate.loader.ast.spi.MultiNaturalIdLoadOptions;
import org.hibernate.metamodel.mapping.Bindable;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstSelectTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement; 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.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl; import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.Callback;
@ -95,8 +91,8 @@ public class MultiNaturalIdLoadingBatcher {
final JdbcServices jdbcServices = sessionFactory.getJdbcServices(); final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final SqlAstSelectTranslator sqlAstTranslator = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ); this.jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
this.jdbcSelect = sqlAstTranslator.translate( sqlSelect ); .translate( null, QueryOptions.NONE );
} }
public <E> List<E> multiLoad(Object[] naturalIdValues, MultiNaturalIdLoadOptions options, SharedSessionContractImplementor session) { public <E> List<E> multiLoad(Object[] naturalIdValues, MultiNaturalIdLoadOptions options, SharedSessionContractImplementor session) {

View File

@ -8,7 +8,6 @@ package org.hibernate.loader.ast.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.HibernateException; 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.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement; 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.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
@ -101,10 +99,7 @@ public class SimpleNaturalIdLoader<T> extends AbstractNaturalIdLoader<T> {
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlSelect );
final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() ); final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
jdbcParamBindings.registerParametersForEachJdbcValue( jdbcParamBindings.registerParametersForEachJdbcValue(
id, id,
Clause.WHERE, Clause.WHERE,
@ -112,7 +107,8 @@ public class SimpleNaturalIdLoader<T> extends AbstractNaturalIdLoader<T> {
jdbcParameters, jdbcParameters,
session session
); );
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
.translate( jdbcParamBindings, QueryOptions.NONE );
final List<Object[]> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list( final List<Object[]> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
jdbcSelect, jdbcSelect,
@ -186,8 +182,6 @@ public class SimpleNaturalIdLoader<T> extends AbstractNaturalIdLoader<T> {
); );
assert jdbcParameters.size() == 1; assert jdbcParameters.size() == 1;
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlSelect );
final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() ); final JdbcParameterBindings jdbcParamBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
final SingularAttributeMapping attributeMapping = naturalIdMapping().getAttribute(); final SingularAttributeMapping attributeMapping = naturalIdMapping().getAttribute();
@ -198,7 +192,8 @@ public class SimpleNaturalIdLoader<T> extends AbstractNaturalIdLoader<T> {
jdbcParameters, jdbcParameters,
session session
); );
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlSelect )
.translate( jdbcParamBindings, QueryOptions.NONE );
final List<?> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list( final List<?> results = session.getFactory().getJdbcServices().getJdbcSelectExecutor().list(
jdbcSelect, jdbcSelect,

View File

@ -7,7 +7,6 @@
package org.hibernate.loader.ast.internal; package org.hibernate.loader.ast.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.LockOptions; 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.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement; 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.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl; import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.Callback;
@ -102,8 +100,6 @@ public class SingleIdEntityLoaderDynamicBatch<T> extends SingleIdEntityLoaderSup
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(
getLoadable().getIdentifierMapping().getJdbcTypeCount() getLoadable().getIdentifierMapping().getJdbcTypeCount()
); );
@ -118,6 +114,8 @@ public class SingleIdEntityLoaderDynamicBatch<T> extends SingleIdEntityLoaderSup
); );
assert offset == jdbcParameters.size(); assert offset == jdbcParameters.size();
} }
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
.translate( jdbcParameterBindings, QueryOptions.NONE );
JdbcSelectExecutorStandardImpl.INSTANCE.list( JdbcSelectExecutorStandardImpl.INSTANCE.list(
jdbcSelect, jdbcSelect,

View File

@ -6,7 +6,6 @@
*/ */
package org.hibernate.loader.ast.internal; package org.hibernate.loader.ast.internal;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.LockOptions; 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.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement; 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.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl; import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.Callback;
@ -96,13 +94,10 @@ public class SingleIdLoadPlan<T> implements SingleEntityLoadPlan {
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
final int jdbcTypeCount = restrictivePart.getJdbcTypeCount(); final int jdbcTypeCount = restrictivePart.getJdbcTypeCount();
assert jdbcParameters.size() % jdbcTypeCount == 0; assert jdbcParameters.size() % jdbcTypeCount == 0;
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcTypeCount ); final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcTypeCount );
jdbcSelect.bindFilterJdbcParameters( jdbcParameterBindings );
int offset = 0; int offset = 0;
while ( offset < jdbcParameters.size() ) { while ( offset < jdbcParameters.size() ) {
@ -116,6 +111,8 @@ public class SingleIdLoadPlan<T> implements SingleEntityLoadPlan {
); );
} }
assert offset == jdbcParameters.size(); assert offset == jdbcParameters.size();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
.translate( jdbcParameterBindings, QueryOptions.NONE );
final List list = JdbcSelectExecutorStandardImpl.INSTANCE.list( final List list = JdbcSelectExecutorStandardImpl.INSTANCE.list(
jdbcSelect, jdbcSelect,

View File

@ -8,7 +8,6 @@ package org.hibernate.loader.ast.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.LockOptions; 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.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement; 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.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
@ -86,8 +84,6 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() ); final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
int offset = jdbcParameterBindings.registerParametersForEachJdbcValue( int offset = jdbcParameterBindings.registerParametersForEachJdbcValue(
ukValue, ukValue,
@ -97,6 +93,8 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
session session
); );
assert offset == jdbcParameters.size(); assert offset == jdbcParameters.size();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
.translate( jdbcParameterBindings, QueryOptions.NONE );
final List<Object> list = sessionFactory.getJdbcServices().getJdbcSelectExecutor().list( final List<Object> list = sessionFactory.getJdbcServices().getJdbcSelectExecutor().list(
jdbcSelect, jdbcSelect,
@ -164,8 +162,6 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory(); final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( sqlAst );
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() ); final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
int offset = jdbcParameterBindings.registerParametersForEachJdbcValue( int offset = jdbcParameterBindings.registerParametersForEachJdbcValue(
ukValue, ukValue,
@ -175,6 +171,8 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
session session
); );
assert offset == jdbcParameters.size(); assert offset == jdbcParameters.size();
final JdbcSelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst )
.translate( jdbcParameterBindings, QueryOptions.NONE );
final List<Object> list = sessionFactory.getJdbcServices().getJdbcSelectExecutor().list( final List<Object> list = sessionFactory.getJdbcServices().getJdbcSelectExecutor().list(
jdbcSelect, jdbcSelect,

View File

@ -7,12 +7,14 @@
package org.hibernate.metamodel.mapping; package org.hibernate.metamodel.mapping;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.IndexedConsumer; import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.Clause; 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.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
@ -59,6 +61,17 @@ public interface EntityValuedModelPart extends FetchableContainer {
getEntityMappingType().applySqlSelections( navigablePath, tableGroup, creationState ); 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 @Override
default int getJdbcTypeCount() { default int getJdbcTypeCount() {
int span = 0; int span = 0;

View File

@ -172,6 +172,29 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
TableGroup tableGroup, TableGroup tableGroup,
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { 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() final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState()
.getSqlExpressionResolver(); .getSqlExpressionResolver();
final TableReference rootTableReference; final TableReference rootTableReference;
@ -194,7 +217,7 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
final Expression expression = expressionResolver.resolveSqlExpression( final Expression expression = expressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( rootTableReference, pkColumnName ), SqlExpressionResolver.createColumnReferenceKey( rootTableReference, pkColumnName ),
sqlAstProcessingState -> new ColumnReference( sqlAstProcessingState -> new ColumnReference(
rootTableReference.getIdentificationVariable(), rootTableReference,
pkColumnName, pkColumnName,
false, false,
null, null,
@ -204,45 +227,7 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
) )
); );
final SqlSelection sqlSelection = expressionResolver.resolveSqlSelection( return 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(
expression, expression,
idType.getExpressableJavaTypeDescriptor(), idType.getExpressableJavaTypeDescriptor(),
sessionFactory.getTypeConfiguration() sessionFactory.getTypeConfiguration()

Some files were not shown because too many files have changed in this diff Show More