3333import org .hibernate .sql .model .MutationOperation ;
3434import org .hibernate .tool .schema .extract .spi .SequenceInformationExtractor ;
3535
36+ import static java .lang .Integer .parseInt ;
37+
38+ import static org .hibernate .internal .util .StringHelper .split ;
39+
3640import static org .hibernate .community .dialect .lock .internal .TiDBLockingSupport .TIDB_LOCKING_SUPPORT ;
3741
3842/**
4145 * @author Cong Wang
4246 */
4347public class TiDBDialect extends MySQLDialect {
44-
45- // 8.0.11 is the first MySQL 8.0 GA release.
46- // See also: https://docs.pingcap.com/tidb/stable/mysql-compatibility/
47- private static final DatabaseVersion VERSION80 = DatabaseVersion .make ( 8 , 0 , 11 );
48-
4948 // See also: https://www.pingcap.com/tidb-release-support-policy/
49+ //
50+ // Note this is the minium TiDB version, not the MySQL version TiDB identifies as.
5051 // v5.4 EOL date: 15 Feb 2026
5152 private static final DatabaseVersion MINIMUM_VERSION = DatabaseVersion .make ( 5 , 4 );
5253
54+ private final DatabaseVersion mySQLVersion ;
55+
5356 public TiDBDialect () {
5457 this ( MINIMUM_VERSION );
5558 }
5659
5760 public TiDBDialect (DatabaseVersion version ) {
5861 super ( version );
62+ this .mySQLVersion = DatabaseVersion .make ( 8 , 0 , 11 );
5963 }
6064
6165 public TiDBDialect (DialectResolutionInfo info ) {
62- super ( createVersion ( info , MINIMUM_VERSION ), MySQLServerConfiguration .fromDialectResolutionInfo ( info ) );
66+ super ( fetchDataBaseVersion ( info ), MySQLServerConfiguration .fromDialectResolutionInfo ( info ) );
6367 registerKeywords ( info );
68+ this .mySQLVersion = createVersion ( info , MINIMUM_VERSION );
69+ }
70+
71+
72+ @ Override
73+ public DatabaseVersion determineDatabaseVersion (DialectResolutionInfo info ) {
74+ return fetchDataBaseVersion ( info );
75+ }
76+
77+
78+ private static DatabaseVersion fetchDataBaseVersion (DialectResolutionInfo info ) {
79+ final String versionStringTiDB = info .getDatabaseVersion ();
80+ if ( versionStringTiDB != null ) {
81+ // [8, 0, 11, TiDB, v8, 5, 4]
82+ final String [] components = split ( ".-" , versionStringTiDB );
83+ if ( components .length >= 7 ) {
84+ try {
85+ final int majorVersion = parseInt ( components [4 ].substring (1 ) ); // v8 -> 8
86+ final int minorVersion = parseInt ( components [5 ] );
87+ final int patchLevel = parseInt ( components [6 ] );
88+ return DatabaseVersion .make ( majorVersion , minorVersion , patchLevel );
89+ }
90+ catch (NumberFormatException ex ) {
91+ // Ignore
92+ }
93+ }
94+ }
95+ return MINIMUM_VERSION ;
6496 }
6597
6698 @ Override
6799 public DatabaseVersion getMySQLVersion () {
68- // For simplicity’s sake, configure MySQL 8.0 compatibility
69- return VERSION80 ;
100+ return mySQLVersion ;
70101 }
71102
72103 @ Override
@@ -77,25 +108,32 @@ protected DatabaseVersion getMinimumSupportedVersion() {
77108 @ Override
78109 protected void registerDefaultKeywords () {
79110 super .registerDefaultKeywords ();
80- // TiDB implemented 'Window Functions' of MySQL 8, so the following keywords are reserved.
81- registerKeyword ( "CUME_DIST" );
82- registerKeyword ( "DENSE_RANK" );
83- registerKeyword ( "EXCEPT" );
84- registerKeyword ( "FIRST_VALUE" );
85- registerKeyword ( "GROUPS" );
86- registerKeyword ( "LAG" );
87- registerKeyword ( "LAST_VALUE" );
88- registerKeyword ( "LEAD" );
89- registerKeyword ( "NTH_VALUE" );
90- registerKeyword ( "NTILE" );
91- registerKeyword ( "PERCENT_RANK" );
92- registerKeyword ( "RANK" );
93- registerKeyword ( "ROW_NUMBER" );
111+
112+ if ( getMySQLVersion ().isBefore ( 8 , 0 ) ) {
113+ // TiDB implemented 'Window Functions' of MySQL 8, even in TiDB versions that identify as 5.7
114+ // so the following keywords are reserved.
115+ registerKeyword ( "CUME_DIST" );
116+ registerKeyword ( "DENSE_RANK" );
117+ registerKeyword ( "EXCEPT" );
118+ registerKeyword ( "FIRST_VALUE" );
119+ registerKeyword ( "GROUPS" );
120+ registerKeyword ( "LAG" );
121+ registerKeyword ( "LAST_VALUE" );
122+ registerKeyword ( "LEAD" );
123+ registerKeyword ( "NTH_VALUE" );
124+ registerKeyword ( "NTILE" );
125+ registerKeyword ( "PERCENT_RANK" );
126+ registerKeyword ( "RANK" );
127+ registerKeyword ( "ROW_NUMBER" );
128+ }
94129 }
95130
96131 @ Override
97132 public boolean supportsCascadeDelete () {
98- return false ;
133+ // FK including cascade is supported as experimental feature since TiDB v6.6.0
134+ // FK including cascade is supported as GA feature since TiDB v8.5.0
135+ // https://docs.pingcap.com/tidb/stable/foreign-key/
136+ return getVersion ().isSameOrAfter ( 6 , 6 );
99137 }
100138
101139 @ Override
@@ -146,7 +184,7 @@ protected boolean supportsAliasLocks() {
146184
147185 @ Override
148186 public boolean supportsRowValueConstructorSyntaxInInList () {
149- return getVersion (). isSameOrAfter ( 5 , 7 ) ;
187+ return true ;
150188 }
151189
152190 @ Override
0 commit comments