From 801e6c923b498406de2973e07c00234eacda9b94 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 11 Dec 2024 17:36:53 -0800 Subject: [PATCH] fixes #291 by adding XTDB tips & tricks Signed-off-by: Sean Corfield --- CHANGELOG.md | 1 + doc/getting-started.md | 14 +++++++------- doc/tips-and-tricks.md | 27 ++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c181357..7854a98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Only accretive/fixative changes will be made from now on. * 1.3.next in progress + * Address [#291](https://github.com/seancorfield/next-jdbc/issues/291) by adding an XTDB section to **Tips & Tricks**. * Added XTDB as a supported database for testing via PR [#290](https://github.com/seancorfield/next-jdbc/pull/290). _Note: not all features are tested against XTDB due to several fundamental differences in architecture, mostly around primary key/generated keys and lack of DDL operations (since XTDB is schemaless)._ * Update dev/test dependencies. diff --git a/doc/getting-started.md b/doc/getting-started.md index 90ec12e..d5f8861 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -22,10 +22,10 @@ for `project.clj` or `build.boot`. **In addition, you will need to add dependencies for the JDBC drivers you wish to use for whatever databases you are using. For example:** -* MySQL: `com.mysql/mysql-connector-j {:mvn/version "8.1.0"}` ([search for latest version](https://search.maven.org/artifact/com.mysql/mysql-connector-j)) -* PostgreSQL: `org.postgresql/postgresql {:mvn/version "42.6.0"}` ([search for latest version](https://search.maven.org/artifact/org.postgresql/postgresql)) -* Microsoft SQL Server: `com.microsoft.sqlserver/mssql-jdbc {:mvn/version "12.4.1.jre11"}` ([search for latest version](https://search.maven.org/artifact/com.microsoft.sqlserver/mssql-jdbc)) -* Sqlite: `org.xerial/sqlite-jdbc {:mvn/version "3.43.0.0"}` ([search for latest version](https://search.maven.org/artifact/org.xerial/sqlite-jdbc)) +* MySQL: `com.mysql/mysql-connector-j {:mvn/version "9.1.0"}` ([search for latest version](https://search.maven.org/artifact/com.mysql/mysql-connector-j)) +* PostgreSQL: `org.postgresql/postgresql {:mvn/version "42.7.4"}` ([search for latest version](https://search.maven.org/artifact/org.postgresql/postgresql)) +* Microsoft SQL Server: `com.microsoft.sqlserver/mssql-jdbc {:mvn/version "12.8.1.jre11"}` ([search for latest version](https://search.maven.org/artifact/com.microsoft.sqlserver/mssql-jdbc)) +* Sqlite: `org.xerial/sqlite-jdbc {:mvn/version "3.47.1.0"}` ([search for latest version](https://search.maven.org/artifact/org.xerial/sqlite-jdbc)) > Note: these are the versions that `next.jdbc` is tested against but there may be more recent versions and those should generally work too -- click the "search for latest version" link to see all available versions of those drivers on Maven Central. You can see the full list of drivers and versions that `next.jdbc` is tested against in [the project's `deps.edn` file](https://github.com/seancorfield/next-jdbc/blob/develop/deps.edn#L10-L27), but many other JDBC drivers for other databases should also work (e.g., Oracle, Red Shift). @@ -39,7 +39,7 @@ For the examples in this documentation, we will use a local H2 database on disk, ;; deps.edn {:deps {org.clojure/clojure {:mvn/version "1.12.0"} com.github.seancorfield/next.jdbc {:mvn/version "1.3.967"} - com.h2database/h2 {:mvn/version "2.2.224"}}} + com.h2database/h2 {:mvn/version "2.3.232"}}} ``` ### Create & Populate a Database @@ -487,9 +487,9 @@ Not all databases support using a `PreparedStatement` for every type of SQL oper First, you need to add the connection pooling library as a dependency, e.g., ```clojure -com.zaxxer/HikariCP {:mvn/version "5.0.1"} +com.zaxxer/HikariCP {:mvn/version "6.2.1"} ;; or: -com.mchange/c3p0 {:mvn/version "0.9.5.5"} +com.mchange/c3p0 {:mvn/version "0.10.1"} ``` _Check those libraries' documentation for the latest version to use!_ diff --git a/doc/tips-and-tricks.md b/doc/tips-and-tricks.md index 76bb41c..882d15e 100644 --- a/doc/tips-and-tricks.md +++ b/doc/tips-and-tricks.md @@ -55,7 +55,7 @@ be very database-specific. Some database drivers **don't** use the hierarchy above -- notably PostgreSQL, which has a generic `PSQLException` type with its own subclasses and semantics. See [PostgreSQL JDBC issue #963](https://github.com/pgjdbc/pgjdbc/issues/963) for a discussion of the difficulty in adopting the standard JDBC hierarchy -(dating back five years). +(dating back to 2017!). The `java.sql.SQLException` class provides `.getErrorCode()` and `.getSQLState()` methods but the values returned by those are @@ -237,6 +237,7 @@ common approach, there is also a non-JDBC Clojure/Java driver for PostgreSQL cal quite a bit faster than using JDBC. When you use `:return-keys true` with `execute!` or `execute-one!` (or you use `insert!`), PostgreSQL returns the entire inserted row (unlike nearly every other database that just returns any generated keys!). +_[It seems to achieve this by the equivalent of automatically appending `RETURNING *` to your SQL, if necessary.]_ The default result set builder for `next.jdbc` is `as-qualified-maps` which uses the `.getTableName()` method on `ResultSetMetaData` to qualify the @@ -574,3 +575,27 @@ If you are using `plan`, you'll most likely be accessing columns by just the lab See also [`datafy`, `nav`, and `:schema` > **SQLite**](/doc/datafy-nav-and-schema.md#sqlite) for additional caveats on the `next.jdbc.datafy` namespace when using SQLite. + +## XTDB + +XTDB is a bitemporal, schemaless, document-oriented database that presents +itself as a PostgreSQL-compatible database, in terms of JDBC. It has a number +of SQL extensions, and some differences from common JDBC behavior. See +its documentation for details: +* [SQL Overview](https://docs.xtdb.com/quickstart/sql-overview.html) +* [SQL Queries](https://docs.xtdb.com/reference/main/sql/queries.html) +* [SQL Transactions/DML](https://docs.xtdb.com/reference/main/sql/txs.html) + +`next.jdbc` officially supports XTDB as of 1.3.next but there are some caveats: +* You can use `:dbtype "xtdb"` to identify XTDB as the database type. +* You must specify `:dbname "xtdb"` in the db-spec hash map or JDBC URL. +* XTDB does not support `.getTableName()` so you always get unqualified column names in result sets. +* The `:max-rows` / `:maxRows` options are not (yet) supported by XTDB (use `LIMIT` in your SQL instead). +* The primary key on all tables is `_id` and it must be specified in all `INSERT` operations (no auto-generated keys). +* That means that `next.jdbc.sql/get-by-id` requires the 5-argument call, so that you can specify the `pk-name` as `:_id` and provide an options map. +* If you want to use `next.jdbc`'s built-in `datafy` / `nav` functionality, you need to explicitly specify `:schema-opts {:pk "_id"}` to override the default assumption of `id` as the primary key. +* DML operations (`INSERT`, `UPDATE`, and `DELETE`) are essentially asynchronous in XTDB and therefore can not return an accurate `next.jdbc/update-count` (so it is always 0). +* `INSERT` operations do not return the inserted row (like PostgreSQL does) nor even the provided `_id` primary key. +* That means that the `next.jdbc.defer` namespace functions do not work well with XTDB. +* `next.jdbc.sql/insert-multi!` returns an empty vector for XTDB (since `INSERT` operations do not return keys or update counts). +* The `next.jdbc.result-set/*-kebab-maps` functions (and associated `next.jdbc/*-kebab-opts` option maps) cause leading `_` to be stripped from column names and cannot be used with XTDB (this is inherent in the underlying library that `next.jdbc` relies on -- you can of course write your own custom result set builder function to handle this).