Fork me on GitHub
#sql
<
2022-09-09
>
sheluchin18:09:20

Is there some way to get the db-spec hash map from a Connection?

seancorfield18:09:57

No, but this method on Connection provides DB-specific information that might include (some of) what you want: https://docs.oracle.com/en/java/javase/17/docs/api/java.sql/java/sql/Connection.html#getClientInfo()

seancorfield18:09:31

For several databases, that returns the JDBC URL which you can pick apart to get dbtype/dbname etc.

sheluchin18:09:33

That method gives me {"ApplicationName" "PostgreSQL JDBC Driver"}, but there is also getURL which returns the URL that can be parsed as you describe. I'm looking for the port, which is in there. I have my test fixtures set up similar to how next.jdbc sets it up, so I can get the connection set up in my tests. My code, however, just expects the db-spec (passed around in the config) and creates the connection on its own. Does parsing the URL seem like the logical approach here?

seancorfield18:09:14

There's no getURL() method on Connection.

seancorfield18:09:29

The test fixtures in next.jdbc have the db-spec and the DataSource available (not Connection) so I think you're a bit confused?

sheluchin19:09:47

I'm taking the ds that the fixture makes available and creating a Connection in my tests.

(type (fix/ds))                                   
; => org.postgresql.ds.PGSimpleDataSource         
(type (jdbc/get-connection (fix/ds)))             
; => org.postgresql.jdbc.PgConnection             
(.getURL (jdbc/get-connection (fix/ds)))          
; => "jdbc:" 
There is a comment in the next.jdbc fixture:
;; this is just a dummy db-spec -- it's handled in with-test-db below
which I understand to mean that it isn't actually applied to EmbeddedPostgres, because it's not reflected in the connection information I see in the URL. I'm just getting started with automated testing here so I'm most likely missing something indeed.

sheluchin19:09:44

One other way:

(jdbc/execute-one! (fix/ds) ["select inet_server_port()"]) 
; => {:inet_server_port 33745}                             
https://www.postgresql.org/docs/current/functions-info.html#FUNCTIONS-INFO-SESSION-TABLE

seancorfield20:09:29

If you load next.jdbc.datafy and then datafy the Connection, you get lots of information (`clojure.core.protocols/datafy`):

:DBVersionNumber - 14.5
:URL - jdbc:
:adaptiveFetch - false
:autoCommit - true
:autosave - #object[org.postgresql.jdbc.AutoSave 0x27002c5a NEVER]
:backendPID - 9973
:catalog - postgres
:class - org.postgresql.jdbc.PgConnection
:clientInfo - #object[java.util.Properties 0x19a920d1 {ApplicationName=PostgreSQL JDBC Driver}]
:closed - false
:columnSanitiserDisabled - false
:copyAPI - #object[org.postgresql.copy.CopyManager 0x6c861b25 org.postgresql.copy.CopyManager@6c861b25]
:cursorName - nil
...

seancorfield20:09:15

So I think you were getting .getURL from the PgConnection type directly, since Connection does not have it. Overall, I would advise you to write code assuming a DataSource -- since in production you'd want to use a connection pooled datasource such as HikariCP produces, and that's what next.jdbc does for the tests now that I look at it:

(reset! test-datasource
                (.getPostgresDatabase ^EmbeddedPostgres @embedded-pg))

seancorfield20:09:34

and for all other DBs:

(reset! test-datasource (jdbc/get-datasource db)))

seancorfield20:09:11

all the next.jdbc functions accept a DataSource (and that's also going to be much more efficient than trying to work with db-spec hash maps!).

sheluchin21:09:29

That clears up many of my questions. I just don't understand how that snippet shows that the next.jdbc tests are using a pooled datasource. Could you please explain that bit?

seancorfield22:09:00

No, they're not using a pooled datasource -- just a regular datasource. But you can easily swap a pooled datasource for that. What I'm saying is: write your code to expect a datasource, not a db-spec hash map.

sheluchin22:09:52

Ah, okay. I understand now. Thanks very much, @U04V70XH6.

seancorfield22:09:19

Mostly, it's transparent: calling get-connection on a db-spec calls get-datasource under the hood and then calls get-connection on that.