sql

All things SQL and JDBC...
seancorfield 2020-06-06T00:46:02.194900Z

Q: Embedded PostgreSQL -- https://github.com/opentable/otj-pg-embedded -- I'm trying to find documentation that indicates what features are not available in this. Anyone have suggestions/pointers?

seancorfield 2020-06-06T00:55:12.195900Z

OK, I think I finally have my answer! Embedded PostgreSQL is equivalent to 10.11 and stored procs didn't arrive until 11.x so it doesn't support them.

seancorfield 2020-06-06T01:24:10.197100Z

I switched to a fork of OpenTable's version that has support for later versions of the database (currently testing with 12.2.0!). This is all about stored procedure support in next.jdbc and multiple result sets.

seancorfield 2020-06-06T02:45:06.197700Z

And this has now allowed me to test next.jdbc against PostgreSQL 12.2.0 on macOS, Windows, and Linux. Yay!

6👏
borkdude 2020-06-06T10:20:07.198200Z

good to know!

dharrigan 2020-06-06T11:19:25.199900Z

Would it be worthwhile to explore TestContainers? I use it in my Kotlin Projects. It uses Docker to pull down an instance of Postgresql, launches it, then you can run whatever (tests) against it?

dharrigan 2020-06-06T11:19:51.200400Z

It works really well on a CI pipeline, and you're guaranteed to be using officially released docker versions of popular databases

dharrigan 2020-06-06T11:20:08.200600Z

https://www.testcontainers.org/

seancorfield 2020-06-06T12:49:16.204400Z

@dharrigan I use a Docker container for testing SQL Server and Percona (MYSQL) but I don't have that facility on all of my machines (for complicated reasons) and most folks seem to use PostgreSQL so it's important to test that on every platform.

dharrigan 2020-06-06T12:56:30.205Z

absolutely, but test containers also runs on Windows too (and Mac)

dharrigan 2020-06-06T12:57:08.205800Z

It was a suggestion 🙂 Does the embedded postgresql add to the size of the repo?

seancorfield 2020-06-06T15:25:29.206200Z

Nope it is just a test dependency.

seancorfield 2020-06-06T15:26:43.207600Z

And this is for my local development convenience so I can test against PG when I'm traveling / offline, with needing to actually install it and set it up.

seancorfield 2020-06-06T15:27:45.208800Z

But I will look at test containers (it was just the middle of the night when I responded to your previous message 🙃

seancorfield 2020-06-06T15:52:53.209700Z

Just checked @dharrigan -- test containers requires Docker to run so it won't be suitable for me, for the same reasons Docker already isn't: I can't run it on some of my machines.

seancorfield 2020-06-06T15:53:16.210200Z

(but thanks for the pointer -- I'll read up on it in more detail another time)

dharrigan 2020-06-06T16:00:13.210400Z

No problemo 🙂

seancorfield 2020-06-06T18:04:48.213600Z

OK, I have multiple result sets coming back from stored procedures in HSQLDB, MySQL, and MS SQL Server. I cannot figure out how to do it in PostgreSQL 😞 PG accepts the CREATE PROCEDURE statement with two SELECT statements in it, but only returns an update count (of zero). My Bing results for this seem to suggest that, as of late 2018 at least, the PG team were not planning to add dynamic result sets (which I've had to use for HSQLDB) but considered returning (a fix number of) multiple result sets to be a "possible future feature".

seancorfield 2020-06-06T18:06:26.214300Z

For MySQL/SQL Server, a simple body with two SELECT statements is enough.

seancorfield 2020-06-06T18:07:58.215800Z

For HSQLDB, I had to DECLARE result1 CURSOR WITH RETURN FOR SELECT ... for each query (`result1`, result1, etc) and then end the procedure with OPEN result1; OPEN result2; -- does PostgreSQL require something similar?

seancorfield 2020-06-06T18:10:04.216800Z

(feel free to pull branch issue-117 and have a play with it -- right now, only execute! on a DataSource supports this, via :multi-rs true)

seancorfield 2020-06-06T18:11:12.218100Z

My current thinking on this is to return a flat continuous result set data structure with {:next.jdbc/result-set N} as a delimiter "record" showing the end of each result set (omitted at the end so they are interleaved, technically speaking).

seancorfield 2020-06-06T18:13:49.220800Z

This followed from the fact that you can get a mix of update counts and result sets interleaved so having an explicit, detectable row between each sequence of result set rows seemed reasonable. Another possibility is to return a full sequence of results which might be easier to deal with. I'd be happy to support multiple formats if folks think they might be useful. Since it's an opt-in feature, multiple result formats can be added over time without impacting existing code (`:multi-rs` would then have a set of possible keyword option values).

Vachi 2020-06-06T19:49:47.226800Z

Hi everyone, it is possible to get columns as kebab case in plan!? I did pass an opts parameter with a :builder-fn that converts to kebab-case , if I call (keys row) in the reducing function and print it, it is shown in kebab-case, but when trying to accumulate the value into a collection using kebab-case lookup doesn't work.

Vachi 2020-06-06T19:50:14.227200Z

(def plan-opts {:builder-fn as-kebab-maps})

(defn plan! [ctx stmt]
  (let [q (sql/format stmt)]
    (jdbc/plan (get-connection ctx) q plan-opts)))

(reduce (fn [acc cur]
                          (prn cur) ;; => {:product-attribute/id-product-attribute "a"}
                          (conj acc (:product-attribute/id-product-attribute cur))
                          ) [] (plan! mysql-ctx {:select [:*]
                                                 :from [:product-attribute]}))

=> [nil]

seancorfield 2020-06-06T19:54:31.229400Z

@vachichng I think you're misunderstanding what the docs say about plan. If you call keys on a row inside plan you are going to fully realize that row -- which will use the result set builder (specifically the row builder portion of it). The whole point of plan is to avoid realizing rows, so you should work with native column labels inside the reduction.

seancorfield 2020-06-06T19:55:18.230300Z

That's why it emphasizes that you can use raw column labels to access individual column values inside the reducing function -- or qualified keywords (but the qualifier is deliberately ignored).

seancorfield 2020-06-06T19:56:50.232300Z

The above code could also be simplified to (into [] (map :id_product_attribute) (plan! ...)) I believe.

Vachi 2020-06-06T19:57:18.233100Z

@seancorfield oh, thank you! yeah, I forgot that it's not realized so the builder-fn is not called until realization

seancorfield 2020-06-06T19:57:18.233200Z

Also, calling prn will realize a row which, again, you want to avoid.

seancorfield 2020-06-06T19:57:51.234Z

Yeah, there are actually tests for plan that deliberately pass :builder-fn nil to ensure that the builder isn't used 🙂

Vachi 2020-06-06T19:57:53.234100Z

yeah, it was for debugging

Vachi 2020-06-06T19:58:03.234300Z

thanks Sean!

seancorfield 2020-06-06T20:01:30.234900Z

Feel free to open an issue (or PR) with suggestions to improvement the documentation if you think it can be clarified.

1👍
seancorfield 2020-06-06T20:02:56.235900Z

(I just realized that the new InspectableMapifiedResultSet protocol documentation doesn't make it clear which functions cause realization -- I need to update that! https://cljdoc.org/d/seancorfield/next.jdbc/1.0.462/api/next.jdbc.result-set#InspectableMapifiedResultSet )