New XWiki API to extend the Hibernate dialects

Hi devs,

I’ve been wanting to add XWiki side drivers/dialects since a long while. The first idea is to remove all that generic if/else based code related to database operations. This would also make it a lot easier to extract all the code related to unsupported databases (H2, MSSQL, Derby, DB2, etc.) in dedicated contrib extensions where it would be easier to improve and test for contributors. And of course it would also make possible for someone to provide an extension to support another database.

So in the context of Loading... I’m trying to start a new API for it.

I would like to start a first version that looks like the following:

  • The new concept would be called “HibernateAdpater” (trying to find a name different from “Driver”, taken by JDBC and “Dialect”, taken by Hibernate and which is actually a bit different in practice since main dialect’s job is to generate SQL queries pieces) but if you have better ideas don’t hesitate
  • We call all HibernateAdapterProvider components one by one (with the metadata about the engine found by JDBC, DatabaseMetaData) until we get a HibernateAdapter instance. In practice we’ll have for now a MariaDB provider for MariaDB engine with a higher priority that the default provider which simply lookup the right adapter based on the DatabaseProduct. The reason I need something different for MariaDB for once is that there are slight differences in the way to access the innodb row format between MySQL and MariaDB unfortunately
  • in the first version, I would like to add to this new adapter API everything I need to implement table compression init :
    • updateDatabase: execute what’s currently in updateDatabase and add its own stuff (in my case a few alter table since I could not find a clean way to pass to the Hibernate init tool the compression of for MySQL, MariaDB and Oracle tables)
    • move HibernateStore#getConfiguredTableName renamed as getTableName
    • maybe a few more that I notice during the implementation
  • eventually we move to this new API all the generic code for which we currently have a bunch of if/else in com.xpn.xwiki.internal.store.hibernate.HibernateStore and in com.xpn.xwiki.store.XWikiHibernate* (and maybe other places)

WDYT ?

Sounds good and a good idea.

Not sure I understand the need for several HibernateAdapterProvider implementations to be called one by one. Why not use the JDBC DatabaseMetaData info to get the DB name and lookup the HibernateAdapter component having the DB name as hint? Is it because there can be several DB names for the same DB, depending on the JDBC driver used, and you want to delegate the knowledge of these different names to the implementation? Now, even with different names, we could imagine several component registrations or have a single mapping component that knows all the names. The problem with the chaining is that it’s not performant even if we won’t have tons of implementing components.

Thx

It would be enough to use DatabaseMetaData#getDatabaseProductName() as hint for my immediate need, but DatabaseMetaData exposes far more than the product name, so there is no reason to limit ourselves to have one adapter per product name. Some adapters might depend on various criteria (it’s the case in Hibernate for example, where you have many different dialects for the same product name, which depends on the product version, etc.).

This is something which is done only once at startup (when initializing the database) and has no reason to be slow since it’s about checking values in the already loaded DatabaseMetaData. I see no reason for it to not be instant most of the time.

ok, thx for the clarifications.

A pull request with what this proposal could look like in practice can be found on XWIKI-22613: Updating the history can take a very long time when there are a lot of objects by tmortagne · Pull Request #3788 · xwiki/xwiki-platform · GitHub.