sql

All things SQL and JDBC...
orestis 2020-02-19T13:37:19.223400Z

I have a Postgres query that should return a java.time.LocalDate since my column is DATE: https://jdbc.postgresql.org/documentation/head/8-date-time.html -- but instead I'm seeing java.sql.Date as the class. I wonder if I have to do something special with next.jdbc?

orestis 2020-02-19T13:39:13.223900Z

(-> (jdbc/execute-one! DS ["select current_timestamp::date"])
      :current_timestamp
      class)
;=> java.sql.Date

orestis 2020-02-19T13:39:30.224300Z

Doesn't help that Clojure prints this as an #inst "..."

orestis 2020-02-19T13:44:00.224700Z

Ah, a java.sql.Date is actually a java.util.Date.

orestis 2020-02-19T13:44:09.225Z

Anyway, doing this:

(extend-protocol next.jdbc.result-set/ReadableColumn
  java.sql.Date
  (read-column-by-label [^java.sql.Date v label]
    (.toLocalDate v))
  (read-column-by-index [^java.sql.Date v rs-meta idx]
    (.toLocalDate v)))

orestis 2020-02-19T13:44:32.225600Z

does the trick. But I'm confused on the whole casting of values that JDBC / next.jdbc does.

seancorfield 2020-02-19T18:18:45.226500Z

@orestis next.jdbc doesn't do any casting by default -- it relies entirely on the JDBC driver. Whatever the driver gives you back (as an Object) is what you get.

seancorfield 2020-02-19T18:20:21.228300Z

If you require the (optional) next.jdbc.date-time namespace, then you get a bunch of coercions around date/time -- particularly useful for PostgreSQL since it sometimes doesn't do certain basic coercions. But bear in mind, loading those protocol extensions means you "buy in" for your whole application.

orestis 2020-02-19T18:20:47.229300Z

I see that JDBC has versions, is that a historical artifact and everyone is at the latest?

seancorfield 2020-02-19T18:21:11.229600Z

(and that ns is for inbound -- Clojure to JDBC -- coercions, not outbound)

seancorfield 2020-02-19T18:21:21.229900Z

Not sure what you mean about "JDBC has versions"?

orestis 2020-02-19T18:22:29.230100Z

> The PostgreSQL™ JDBC driver implements native support for the Java 8 Date and Time API (JSR-310) using JDBC 4.2.

orestis 2020-02-19T18:22:44.230500Z

From the page I linked above

orestis 2020-02-19T18:22:55.231Z

(On mobile sorry if replies are terse)

seancorfield 2020-02-19T18:24:36.232300Z

No idea about PG -- it def. does some weird stuff. I added next.jdbc.date-time because it would not do those coercions automatically.

orestis 2020-02-19T18:24:53.233Z

LocalDate localDate = rs.getObject(1, LocalDate.class));

seancorfield 2020-02-19T18:24:57.233200Z

Either way, next.jdbc just passes objects back and forth to JDBC.

orestis 2020-02-19T18:25:04.233500Z

This is the example they give

seancorfield 2020-02-19T18:25:16.233900Z

Right, which is not the call next.jdbc makes.

seancorfield 2020-02-19T18:27:08.235700Z

next.jdbc uses the single argument call because it has to be generic.

orestis 2020-02-19T18:27:19.236100Z

Ah, so that’s an overload to get a specific class if you already know what to expect

seancorfield 2020-02-19T18:28:40.236700Z

Right, which next.jdbc cannot know in advance -- since it is a type from "user code" and not from the database schema.

orestis 2020-02-19T18:29:38.237300Z

Ok that’s clearer now, thanks

orestis 2020-02-19T18:30:53.239Z

Last question, on the ReadbleColunn protocol, when is the function with the column name called? In some light testing I only saw the version with the column Index called.

orestis 2020-02-19T18:31:44.240400Z

And also since it looks to be a global protocol, I can’t see how the name or index are useful. Unless you can customize this per call and I haven’t found out yet

seancorfield 2020-02-19T18:33:13.240700Z

That's explained in the docs somewhere...

seancorfield 2020-02-19T18:33:28.241100Z

(I'm eating breakfast so I can't look right now)

seancorfield 2020-02-19T18:38:46.242600Z

plan uses just the column label. execute! uses the column index and passes the result set metadata so you can look in the metadata for more information about the (JDBC) type of that column, as well as get its name etc.

seancorfield 2020-02-19T18:44:17.243300Z

(`plan` is deliberately restrictive so that it can be as fast as possible, so it avoids fetching result set metadata if possible)

orestis 2020-02-19T18:49:57.243800Z

Thanks, sorry for interrupting your breakfast!

seancorfield 2020-02-19T18:52:06.244800Z

NP. I looked in the docs once I'd finished (eggs over easy and maple pork links!).

orestis 2020-02-19T18:52:38.245600Z

I will try to write a JDBC 101 because frankly the situation was really confusing to me when I started dealing with all those things :)

orestis 2020-02-19T18:53:44.246600Z

Yum! Gotta love the options in California. I miss being in a Mediterranean climate. (Greek living in Denmark)

seancorfield 2020-02-19T18:55:01.246800Z

That was home-cooked 🙂

seancorfield 2020-02-19T18:55:26.247Z

But, yeah, California has some awesome food options.

seancorfield 2020-02-19T18:55:54.247500Z

Happy to extend the docs with that, if you feel like contributing via a PR!

orestis 2020-02-19T18:57:43.248Z

Yeah I will try! Thanks for all the work you’re doing!

orestis 2020-02-19T18:58:07.248800Z

Gotta put the baby to sleep... good night/day!