From 581df5839fc30634e26bbe306b92c476d46042f9 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 15 Mar 2024 16:18:09 -0700 Subject: [PATCH] fix #275 by noting the potential performance overhead of qualified column names with postgres Signed-off-by: Sean Corfield --- CHANGELOG.md | 1 + doc/getting-started.md | 1 + doc/tips-and-tricks.md | 9 +++++++++ 3 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1ffebf..8255b4d 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 [#275](https://github.com/seancorfield/next-jdbc/issues/275) by noting that PostgreSQL may perform additional SQL queries to produce table names used in qualified result set builders. * Address [#268](https://github.com/seancorfield/next-jdbc/issues/268) by expanding the documentation around `insert-multi!` and `insert!`. * Update dependency versions (including Clojure). * Code cleanup per `clj-kondo`. diff --git a/doc/getting-started.md b/doc/getting-started.md index f7b68b3..6aef891 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -134,6 +134,7 @@ user=> Relying on the default result set builder -- and table-qualified column names -- is the recommended approach to take, if possible, with a few caveats: * MS SQL Server produces unqualified column names by default (see [**Tips & Tricks**](/doc/tips-and-tricks.md) for how to get table names back from MS SQL Server), * Oracle's JDBC driver doesn't support `.getTableName()` so it will only produce unqualified column names (also mentioned in **Tips & Tricks**), +* PostgreSQL's JDBC driver performs an extra SQL query to get the necessary metadata, so there is some overhead to using qualified column names (also mentioned in **Tips & Tricks**), * If your SQL query joins tables in a way that produces duplicate column names, and you use unqualified column names, then those duplicated column names will conflict and you will get only one of them in your result -- use aliases in SQL (`as`) to make the column names distinct, * If your SQL query joins a table to itself under different aliases, the _qualified_ column names will conflict because they are based on the underlying table name provided by the JDBC driver rather the alias you used in your query -- again, use aliases in SQL to make those column names distinct. diff --git a/doc/tips-and-tricks.md b/doc/tips-and-tricks.md index 9eba4e5..ac60fca 100644 --- a/doc/tips-and-tricks.md +++ b/doc/tips-and-tricks.md @@ -229,6 +229,15 @@ is the best way to ensure the statement is properly closed after use. 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!). +The default result set builder for `next.jdbc` is `as-qualified-maps` which +uses the `.getTableName()` method on `ResultSetMetaData` to qualify the +columns in the result set. While some database drivers have this information +on hand from the original SQL operation, PostgreSQL's JDBC driver does not +and it performs an extra SQL query to fetch table names the first time this +method is called for each query. If you want to avoid those extra queries, +and you can live with unqualified column names, you can use `as-unqualified-maps` +as the result set builder instead. + If you have a query where you want to select where a column is `IN` a sequence of values, you can use `col = ANY(?)` with a native array of the values instead of `IN (?,?,?,,,?)` and a sequence of values. What does this mean for your use of `next.jdbc`? In `plan`, `execute!`, and `execute-one!`, you can use `col = ANY(?)` in the SQL string and a single primitive array parameter, such as `(int-array [1 2 3 4])`. That means that in `next.jdbc.sql`'s functions that take a where clause (`find-by-keys`, `update!`, and `delete!`) you can specify `["col = ANY(?)" (int-array data)]` for what would be a `col IN (?,?,?,,,?)` where clause for other databases and require multiple values.