diff --git a/dialects.adoc b/dialects.adoc index ffbf79132468..159b1e2462d2 100644 --- a/dialects.adoc +++ b/dialects.adoc @@ -1,73 +1,6 @@ = Dialects -A dialect is a class that provides information about the specifics of a database and translators for the SQL dialect of the database. +The content of this file has moved to link:./documentation/src/main/asciidoc/dialect/index.adoc. +Going forward, it will be published in rendered form at https://docs.hibernate.org/stable/orm/dialect/. -== Supported dialects - -Hibernate supports a wide range of dialects out of the box. The following is list of officially supported databases: - -* Apache Derby -* Cockroach -* Google Spanner -* H2 -* HSQLDB -* IBM DB2 LUW -* IBM DB2 iSeries -* IBM DB2 z/OS -* MariaDB -* MySQL -* Oracle -* PostgreSQL -* Postgres Plus -* SAP HANA -* SQL Server -* Sybase ASE - -Usually, Hibernate supports at least the database version that is also still supported by the respective vendor. -In many cases though, Hibernate supports even older versions of the databases, -but the support for these versions is not guaranteed. - -Apart from the Hibernate team supported dialects, there are also community dialects. - -== Community dialects - -As of Hibernate 6.0, the Hibernate team decided to provide a clear way forward for community contributed dialects. -The `hibernate-core` artifact had many legacy dialects before 6.0 that were only tested and maintained on a best effort basis. - -More and more database vendors requested to integrate a dialect for their database and even provided a PR with a dialect, -but the Hibernate team didn't want to add new dialects for databases that might not have a wide adoption -or any automated testing into the `hibernate-core` artifact. Even though the dialect was supposedly maintained by the vendor, -the Hibernate team was burdened with reviewing questions, issues and PRs that relate to these dialects. - -To give database vendors and the community a clear way forward, the Hibernate team decided to introduce a new artifact, -called `hibernate-community-dialects` which is the new home for dialects that are maintained by vendors or individuals. -Starting with Hibernate 6.0 the `hibernate-core` artifact will only contain dialects that are supported and tested by the Hibernate team. -All the legacy dialects are moved to the `hibernate-community-dialects` artifact to have a clear separation based on the quality of the dialect. - -Issues with dialects in the `hibernate-community-dialects` are usually not considered by the Hibernate team, -as the community is responsible for providing fixes and improving the dialects for newer database versions or ORM capabilities. - -== Requirements for moving to hibernate-core - -If a database vendor wants their database dialect to be included in the `hibernate-core` artifact, -several requirements have to be fulfilled: - -* The vendor must provide access to a dedicated database server that can be used for testing -* The vendor must provide contact details to at least one employee who is mainly responsible for the maintenance of the dialect -* The responsible employee of the vendor must actively monitor and react to failures of the testsuite against the respective database -* The responsible employee of the vendor must ensure the testsuite is configured correctly in order for it to succeed on the respective database -* If the responsible employee of the vendor leaves the company, the vendor must provide contact details to a new responsible employee - -In case the responsible employee is unreachable for a longer period or issues with the dialect are not attended to in a timely manner, -the Hibernate team will move the dialect back to the `hibernate-community-dialects` artifact. - -The requirements for the database server are: - -* JDK 8 installed through e.g. `sudo yum install -y java-1.8.0-openjdk-devel` -* JDK 11 installed through e.g. `sudo yum install -y java-11-openjdk-devel` -* Git installed through e.g. `sudo yum install -y git` -* Access to the database through non-confidential credentials -* Access via SSH through confidential credentials - -Get in touch with the Hibernate team on https://hibernate.zulipchat.com/#narrow/stream/132096-hibernate-user[Zulip] -if you want to request the move of your dialect to hibernate-core. \ No newline at end of file +If you ended up here following a link, please ask whoever published that link to update it. \ No newline at end of file diff --git a/documentation/documentation.gradle b/documentation/documentation.gradle index 973b3e3e3fd4..a640428150c3 100644 --- a/documentation/documentation.gradle +++ b/documentation/documentation.gradle @@ -139,6 +139,7 @@ dependencies { reportAggregation project(':hibernate-ant') reportAggregation project(':hibernate-enhance-maven-plugin') reportAggregation project(':hibernate-jpamodelgen') + reportAggregation project(':hibernate-community-dialects') asciidoctorGems 'rubygems:rouge:4.1.1' @@ -692,7 +693,7 @@ def renderUserGuideHtmlTask = tasks.register( 'renderUserGuideHtml', Asciidoctor inputs.property "hibernate-version", project.ormVersion inputs.file( generateSettingsDocTask.get().outputFile ) - dependsOn generateSettingsDocTask, generateDialectTableReport + dependsOn generateSettingsDocTask sourceDir = file( 'src/main/asciidoc/userguide' ) sources { @@ -807,6 +808,30 @@ def renderMigrationGuideTask = tasks.register( "renderMigrationGuide", Asciidoct } } +// Dialect Guide ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def renderDialectGuideTask = tasks.register( 'renderDialectGuide', AsciidoctorTask ) { task -> + group = "Documentation" + description = 'Renders the Dialect guide in HTML format using Asciidoctor.' + inputs.property "hibernate-version", project.ormVersion + dependsOn generateDialectTableReport, generateCommunityDialectTableReport + + sourceDir = file( 'src/main/asciidoc/dialect' ) + sources 'dialect.adoc' + outputDir = layout.buildDirectory.dir( 'asciidoc/dialect' ) + + attributes linkcss: true, stylesheet: "css/hibernate.css", + 'generated-report-dir': layout.buildDirectory.dir( 'orm/generated' ).get() + + task.resources { + from( 'src/main/style/asciidoctor' ) { + include 'images/**' + } + from( 'src/main/style/asciidoctor' ) { + include 'css/**' + } + } +} // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ORM Reports @@ -836,34 +861,8 @@ def renderLoggingReportTask = tasks.register( 'renderLoggingReport', Asciidoctor } } -def renderDialectReportTask = tasks.register( 'renderDialectReport', AsciidoctorTask ) { task -> - task.group = "hibernate-reports" - task.description = 'Renders the supported Dialect report in HTML format using Asciidoctor.' - task.dependsOn "generateDialectReport" - task.dependsOn "generateDialectTableReport" - - task.inputs.property "version", project.ormVersion - - task.sourceDir = layout.buildDirectory.dir( 'orm/generated/dialect' ) - task.sources 'dialect.adoc' - - task.outputDir = project.layout.buildDirectory.dir( 'asciidoc/dialect' ) - - task.attributes linkcss: true, - stylesheet: "css/hibernate.css" - - task.resources { - from( 'src/main/style/asciidoctor' ) { - include 'images/**' - } - from( 'src/main/style/asciidoctor' ) { - include 'css/**' - } - } -} - def generateReportsTask = tasks.named( "generateReports" ) { - dependsOn renderLoggingReportTask, renderDialectReportTask + dependsOn renderLoggingReportTask } @@ -882,6 +881,7 @@ def buildDocsTask = tasks.register( 'buildDocs' ) { task -> task.dependsOn renderRepositoriesTask task.dependsOn renderIntegrationGuidesTask task.dependsOn renderTopicalGuidesTask + task.dependsOn renderDialectGuideTask task.dependsOn generateReportsTask task.dependsOn renderMigrationGuideTask } diff --git a/documentation/src/main/asciidoc/dialect/dialect.adoc b/documentation/src/main/asciidoc/dialect/dialect.adoc new file mode 100644 index 000000000000..a35b85dbfbe6 --- /dev/null +++ b/documentation/src/main/asciidoc/dialect/dialect.adoc @@ -0,0 +1,82 @@ +:shared-attributes-dir: ../shared/ + +include::{shared-attributes-dir}/common-attributes.adoc[] +include::{shared-attributes-dir}/url-attributes.adoc[] +include::{shared-attributes-dir}/filesystem-attributes.adoc[] +include::{shared-attributes-dir}/renderer-attributes.adoc[] + += Dialects +:toc2: +:toclevels: 1 +:sectanchors: + +A dialect is a class that provides information about the specifics of a database and translators for the SQL dialect of the database. + +== Supported dialects + +Hibernate ORM supports a wide range of dialects out of the box. + +Usually, Hibernate supports at least the database version that is also still supported by the respective vendor. +In many cases though, Hibernate supports even older versions of the databases, +but the support for these versions is not guaranteed. + +Below is a list of supported dialects and the minimum required version of the database. + +include::{generated-report-dir}/dialect/dialect-table.adoc[] + +[[community-dialects]] +== Community dialects + +Community dialects are not included in `org.hibernate.orm:hibernate-core` and require an additional dependency to `org.hibernate.orm:hibernate-community-dialects`. + +These dialects are not directly supported by the Hibernate team: + +* The Hibernate ORM CI does not run any test against these dialects. +* The Hibernate team will not address issues reported against these dialect. + +Instead, the dialects are maintained on a best-effort basis by vendors or individuals. + +Below is a list of community dialects and the minimum required version of the database. + +include::{generated-report-dir}/dialect/dialect-table-community.adoc[] + +[NOTE] +==== +Community dialects were introduced in Hibernate ORM 6.0. + +The `hibernate-core` artifact had many legacy dialects before 6.0 that were only tested and maintained on a best effort basis. +More and more database vendors requested to integrate a dialect for their database and even provided a PR with a dialect, +but the Hibernate team didn't want to add new dialects for databases that might not have a wide adoption +or any automated testing into the `hibernate-core` artifact. Even though the dialect was supposedly maintained by the vendor, +the Hibernate team was burdened with reviewing questions, issues and PRs that relate to these dialects. + +To give database vendors and the community a clear way forward, the Hibernate team decided to introduce a new artifact, +called `hibernate-community-dialects` which is the new home for dialects that are maintained by vendors or individuals. + +Moving forward, the `hibernate-core` artifact will only contain dialects that are supported and tested by the Hibernate team. +All the legacy dialects were moved to the `hibernate-community-dialects` artifact to have a clear separation based on the quality of the dialect. +==== + +== Requirements for moving from `hibernate-community-dialects` to `hibernate-core` + +If a database vendor wants their database dialect to be included in the `hibernate-core` artifact, +several requirements have to be fulfilled: + +* The vendor must provide access to a dedicated database server that can be used for testing +* The vendor must provide contact details to at least one employee who is mainly responsible for the maintenance of the dialect +* The responsible employee of the vendor must actively monitor and react to failures of the testsuite against the respective database +* The responsible employee of the vendor must ensure the testsuite is configured correctly in order for it to succeed on the respective database +* If the responsible employee of the vendor leaves the company, the vendor must provide contact details to a new responsible employee + +In case the responsible employee is unreachable for a longer period or issues with the dialect are not attended to in a timely manner, +the Hibernate team will move the dialect back to the `hibernate-community-dialects` artifact. + +The requirements for the database server are: + +* JDK 17 installed +* Git installed +* Access to the database through non-confidential credentials +* Access via SSH through confidential credentials + +Get in touch with the Hibernate team on https://hibernate.zulipchat.com/#narrow/stream/132096-hibernate-user[Zulip] +if you want to request the move of your dialect to hibernate-core. diff --git a/documentation/src/main/asciidoc/introduction/Configuration.adoc b/documentation/src/main/asciidoc/introduction/Configuration.adoc index 9293cf6e0ce1..d598db1b058b 100644 --- a/documentation/src/main/asciidoc/introduction/Configuration.adoc +++ b/documentation/src/main/asciidoc/introduction/Configuration.adoc @@ -118,6 +118,7 @@ and `com.github.ben-manes.caffeine:jcache` or `org.eclipse:yasson` | <> | `org.hibernate.orm:hibernate-spatial` | <>, for auditing historical data | `org.hibernate.orm:hibernate-envers` +| link:{doc-dialect-url}#community-dialects[Community dialects] | `org.hibernate.orm:hibernate-community-dialects` |=== You might also add the Hibernate {enhancer}[bytecode enhancer] to your diff --git a/documentation/src/main/asciidoc/quickstart/guides/obtaining.adoc b/documentation/src/main/asciidoc/quickstart/guides/obtaining.adoc index 81a9a507dcdc..f0593213481a 100644 --- a/documentation/src/main/asciidoc/quickstart/guides/obtaining.adoc +++ b/documentation/src/main/asciidoc/quickstart/guides/obtaining.adoc @@ -58,7 +58,7 @@ transitive dependencies based on the features being used or not. |hibernate-jcache| Integration with https://jcp.org/en/jsr/detail?id=107$$[JCache], allowing any compliant implementation as a second-level cache provider |hibernate-graalvm| Experimental extension to make it easier to compile applications as a https://www.graalvm.org/[GraalVM] native image |hibernate-micrometer| Integration with https://micrometer.io[Micrometer] metrics -|hibernate-community-dialects| Additional community-supported SQL dialects +|hibernate-community-dialects| Additional link:{doc-dialect-url}#community-dialects[community-supported SQL dialects] |=== [cols="40m,~"] diff --git a/documentation/src/main/asciidoc/shared/url-attributes.adoc b/documentation/src/main/asciidoc/shared/url-attributes.adoc index 12c29a944d4f..46231bdb0566 100644 --- a/documentation/src/main/asciidoc/shared/url-attributes.adoc +++ b/documentation/src/main/asciidoc/shared/url-attributes.adoc @@ -15,9 +15,9 @@ include::./common-attributes.adoc[] :doc-topical-url: {doc-version-base-url}/topical/html_single/ :doc-registries-url: {doc-topical-url}/registries/ServiceRegistries.html :doc-logging-url: {doc-topical-url}/logging/Logging.html +:doc-dialect-url: {doc-version-base-url}/dialect/dialect.html :report-deprecation-url: {doc-version-base-url}/deprecated/deprecating.txt -:report-dialect-url: {doc-version-base-url}/dialect/dialect.html :report-incubating-url: {doc-version-base-url}/incubating/incubating.txt :report-internals-url: {doc-version-base-url}/internals/internal.txt :report-logging-url: {doc-version-base-url}/logging/logging.html diff --git a/documentation/src/main/asciidoc/userguide/chapters/compatibility/Compatibility.adoc b/documentation/src/main/asciidoc/userguide/chapters/compatibility/Compatibility.adoc index 49bae6674020..f554dbe452a1 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/compatibility/Compatibility.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/compatibility/Compatibility.adoc @@ -70,7 +70,7 @@ Maven:: [[compatibility-database]] === Database -Hibernate {fullVersion} is compatible with the following database versions, -provided you use the corresponding <>: +Hibernate {fullVersion}'s compatibility with a given database and version +depends on the dialect being used. -include::{generated-report-dir}/dialect/dialect-table.adoc[] +Refer to the link:{doc-dialect-url}[Dialects] guide for details about both dialects and supported databases. diff --git a/documentation/src/main/asciidoc/userguide/chapters/jdbc/Database_Access.adoc b/documentation/src/main/asciidoc/userguide/chapters/jdbc/Database_Access.adoc index b8fafb17eb7e..c3e99357f8d8 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/jdbc/Database_Access.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/jdbc/Database_Access.adoc @@ -292,5 +292,7 @@ Hibernate abstracts over variations between dialects of SQL via the class `org.h - There's a subclass of `Dialect` for each supported relational database in the package `org.hibernate.dialect`. - Additional community-supported ``Dialect``s are available in the separate module `hibernate-community-dialects`. -In Hibernate 6, it's no longer necessary to explicitly specify a dialect using the configuration property `hibernate.dialect`, and so setting that property is now discouraged. -(An exception is the case of custom user-written ``Dialect``s.) \ No newline at end of file +Starting with Hibernate 6, it's no longer necessary to explicitly specify a dialect using the configuration property `hibernate.dialect`, and so setting that property is now discouraged. +(An exception is the case of custom user-written ``Dialect``s.) + +NOTE: For information about available dialects and compatible database versions, see the link:{doc-dialect-url}[dialect guide]. \ No newline at end of file diff --git a/documentation/src/main/asciidoc/userguide/chapters/portability/Portability.adoc b/documentation/src/main/asciidoc/userguide/chapters/portability/Portability.adoc index 21feacb3964d..07ba060c16b4 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/portability/Portability.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/portability/Portability.adoc @@ -14,7 +14,8 @@ Regardless of the exact scenario, the basic idea is that you want Hibernate to h The first line of portability for Hibernate is the dialect, which is a specialization of the `org.hibernate.dialect.Dialect` contract. A dialect encapsulates all the differences in how Hibernate must communicate with a particular database to accomplish some task like getting a sequence value or structuring a SELECT query. -Hibernate bundles a wide range of dialects for many of the most popular databases. + +Hibernate bundles a wide range of dialects for many of the most popular databases: see the link:{doc-dialect-url}[dialect guide] for details. If you find that your particular database is not among them, it is not terribly difficult to write your own. [[portability-dialectresolver]] diff --git a/local-build-plugins/src/main/java/org/hibernate/orm/post/DialectReportTask.java b/local-build-plugins/src/main/java/org/hibernate/orm/post/DialectReportTask.java index ba751f5a688a..ef0b65099708 100644 --- a/local-build-plugins/src/main/java/org/hibernate/orm/post/DialectReportTask.java +++ b/local-build-plugins/src/main/java/org/hibernate/orm/post/DialectReportTask.java @@ -28,8 +28,6 @@ import org.gradle.api.tasks.SourceSetContainer; import org.gradle.api.tasks.TaskAction; -import org.hibernate.orm.env.HibernateVersion; - import org.jboss.jandex.ClassInfo; import org.jboss.jandex.Index; @@ -39,24 +37,30 @@ * @author Steve Ebersole */ public abstract class DialectReportTask extends AbstractJandexAwareTask { + private final Property sourceProject; + private final Property sourcePackage; private final Property reportFile; - private final Property generateHeading; public DialectReportTask() { - setDescription( "Generates a report of the supported Dialects" ); + setDescription( "Generates a report of Dialects" ); + sourceProject = getProject().getObjects().property(String.class); + sourcePackage = getProject().getObjects().property(String.class); reportFile = getProject().getObjects().fileProperty(); - reportFile.convention( getProject().getLayout().getBuildDirectory().file( "orm/generated/dialect/dialect.adoc" ) ); - generateHeading = getProject().getObjects().property( Boolean.class ).convention( true ); } - @OutputFile - public Property getReportFile() { - return reportFile; + @Input + public Property getSourceProject() { + return sourceProject; } @Input - public Property getGenerateHeading() { - return generateHeading; + public Property getSourcePackage() { + return sourcePackage; + } + + @OutputFile + public Property getReportFile() { + return reportFile; } @Override @@ -66,16 +70,19 @@ protected Provider getTaskReportFileReference() { @TaskAction public void generateDialectReport() { - // the ones we want are all in the hibernate-core project - final Project coreProject = getProject().getRootProject().project( "hibernate-core" ); - final SourceSetContainer sourceSets = coreProject.getExtensions().getByType( SourceSetContainer.class ); + // TODO this probably messes up the cache since we don't declare an explicit dependency to a source set + // but the problem is pre-existing and I don't have time to investigate. + Project sourceProject = getProject().getRootProject().project( this.sourceProject.get() ); + final SourceSetContainer sourceSets = sourceProject.getExtensions().getByType( SourceSetContainer.class ); final SourceSet sourceSet = sourceSets.getByName( SourceSet.MAIN_SOURCE_SET_NAME ); - final ClassLoader classLoader = Helper.asClassLoader( sourceSet, coreProject.getConfigurations().getByName( "testRuntimeClasspath" ) ); + final ClassLoader classLoader = Helper.asClassLoader( sourceSet, sourceProject.getConfigurations().getByName( "testRuntimeClasspath" ) ); final DialectClassDelegate dialectClassDelegate = new DialectClassDelegate( classLoader ); final Index index = getIndexManager().getIndex(); final Collection allDialectClasses = index.getAllKnownSubclasses( DialectClassDelegate.DIALECT_CLASS_NAME ); + String sourcePackagePrefix = this.sourcePackage.get() + "."; + allDialectClasses.removeIf( c -> !c.name().toString().startsWith( sourcePackagePrefix ) ); if ( allDialectClasses.isEmpty() ) { throw new RuntimeException( "Unable to find Dialects" ); } @@ -128,15 +135,6 @@ private void writeDialectReport( private void writeDialectReportHeader(OutputStreamWriter fileWriter) { try { - if ( this.generateHeading.get() ) { - fileWriter.write( "= Supported Dialects\n\n" ); - fileWriter.write( - "Supported Dialects along with the minimum supported version of the underlying database.\n\n\n" ); - - HibernateVersion ormVersion = (HibernateVersion) getProject().getRootProject().getExtensions().getByName( "ormVersion" ); - fileWriter.write( "NOTE: Hibernate version " + ormVersion.getFamily() + "\n\n" ); - } - fileWriter.write( "[cols=\"a,a\", options=\"header\"]\n" ); fileWriter.write( "|===\n" ); fileWriter.write( "|Dialect |Minimum Database Version\n" ); @@ -148,7 +146,10 @@ private void writeDialectReportHeader(OutputStreamWriter fileWriter) { private void writeDialectReportEntry(DialectDelegate dialectDelegate, OutputStreamWriter fileWriter) { try { - final String version = dialectDelegate.getMinimumVersion(); + String version = dialectDelegate.getMinimumVersion(); + if ( "0.0".equals( version ) ) { + version = "N/A"; + } fileWriter.write( '|' ); fileWriter.write( dialectDelegate.getDialectImplClass().getSimpleName() ); fileWriter.write( '|' ); diff --git a/local-build-plugins/src/main/java/org/hibernate/orm/post/ReportGenerationPlugin.java b/local-build-plugins/src/main/java/org/hibernate/orm/post/ReportGenerationPlugin.java index 66bd42a20b34..7fbc1200f681 100644 --- a/local-build-plugins/src/main/java/org/hibernate/orm/post/ReportGenerationPlugin.java +++ b/local-build-plugins/src/main/java/org/hibernate/orm/post/ReportGenerationPlugin.java @@ -57,22 +57,28 @@ public void apply(Project project) { (task) -> task.dependsOn( indexerTask ) ); - final TaskProvider dialectTask = project.getTasks().register( - "generateDialectReport", - DialectReportTask.class, - (task) -> task.dependsOn( indexerTask ) - ); - final TaskProvider dialectTableTask = project.getTasks().register( "generateDialectTableReport", DialectReportTask.class, (task) -> { task.dependsOn( indexerTask ); - task.setProperty( "generateHeading", false ); + task.setProperty( "sourceProject", "hibernate-core" ); + task.setProperty( "sourcePackage", "org.hibernate.dialect" ); task.setProperty( "reportFile", project.getLayout().getBuildDirectory().file( "orm/generated/dialect/dialect-table.adoc" ) ); } ); + final TaskProvider communityDialectTableTask = project.getTasks().register( + "generateCommunityDialectTableReport", + DialectReportTask.class, + (task) -> { + task.dependsOn( indexerTask ); + task.setProperty( "sourceProject", "hibernate-community-dialects" ); + task.setProperty( "sourcePackage", "org.hibernate.community.dialect" ); + task.setProperty( "reportFile", project.getLayout().getBuildDirectory().file( "orm/generated/dialect/dialect-table-community.adoc" ) ); + } + ); + final Task groupingTask = project.getTasks().maybeCreate( "generateReports" ); groupingTask.setGroup( TASK_GROUP_NAME ); groupingTask.dependsOn( indexerTask ); @@ -80,7 +86,7 @@ public void apply(Project project) { groupingTask.dependsOn( deprecationTask ); groupingTask.dependsOn( internalsTask ); groupingTask.dependsOn( loggingTask ); - groupingTask.dependsOn( dialectTask ); groupingTask.dependsOn( dialectTableTask ); + groupingTask.dependsOn( communityDialectTableTask ); } }