This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-14
Channels
- # 100-days-of-code (4)
- # announcements (1)
- # beginners (63)
- # boot (22)
- # braveandtrue (104)
- # calva (3)
- # cider (12)
- # cljs-dev (53)
- # cljsjs (3)
- # cljsrn (1)
- # clojure (180)
- # clojure-dev (14)
- # clojure-italy (4)
- # clojure-nl (11)
- # clojure-spec (15)
- # clojure-uk (60)
- # clojure-ukraine (1)
- # clojurescript (118)
- # clojutre (3)
- # core-async (12)
- # core-logic (17)
- # cursive (19)
- # datomic (45)
- # devcards (4)
- # emacs (7)
- # figwheel-main (218)
- # fulcro (27)
- # funcool (3)
- # graphql (1)
- # jobs (4)
- # leiningen (57)
- # off-topic (71)
- # pedestal (2)
- # portkey (17)
- # re-frame (5)
- # reitit (4)
- # remote-jobs (2)
- # ring (11)
- # rum (2)
- # shadow-cljs (14)
- # specter (11)
- # sql (34)
- # tools-deps (23)
Sounds like you want reducible-query
? @mattsfrey
(built into clojure.java.jdbc
)
http://clojure-doc.org/articles/ecosystem/java_jdbc/using_sql.html#processing-a-result-set-lazily
In particular, pay attention to the Additional Options? section because getting databases to actually fetch results in batches is sometimes non-trivial.
The JDBC world has changed a lot in Clojure in the last few years.
Yeah, if your DB needs that.
And you may need :result-type :forward-only
and probably :fetch-size
(set according to however your DB wants it).
am I correct to make the assumption that
(jdbc/query db-spec expiration-query
{:row-fn handle-row})
will lazily query over the whole table one row at a time?It depends what you mean by "lazily" there...
jdbc/query
realizes the entire result, which is independent of whether the database fetches "lazily" (in batches/chunks).
In your code above, it would return a (fully-realized) sequence of all the results from calling handle-row
on each row fetched from the database.
That's the main difference with reducible-query
-- it doesn't actually do anything until you reduce
it somehow, and you can control what happens with the result accumulation (so you can process a row and essentially "throw away" the result).
The "lazy" in the docs is intended to mean you can process an arbitrarily large result set without bringing it all into memory.
yes that last part is what I mean, I am really just trying to scan over a large db table without loading the entire result set into memory
you need to use a cursor and do that manually (at least with pg) otherwise the jdbc driver will just send all the result over the wire even if you do not consume it (lazily or not)
declare cursor foo for select * from bar
then fetch 1000 from foo
for every fetch and close foo
at the end. You can turn that into a lazy seq with some effort.
not sure reducible-query helps doing that at all, at least with pg, but I am not familiar with it
@mpenet No, you do not need to manually use a cursor for this. Setting auto-commit false on the connection, setting result-type forward-only and a fetch-size is all you should need. Folks have actually verified that works on Postgres with java.jdbc
BTW.
(I don't use Postgres -- I have to rely on others to test & verify this stuff for me -- but all that stuff in the docs, and the underlying features I added to java.jdbc
, is specifically about getting the DB to stream chunks of a result set)
If you look through the closed JIRA tickets for java.jdbc
you should see where folks were testing and verifying the lazy processing behavior...
I see only these: https://dev.clojure.org/jira/secure/IssueNavigator.jspa?
anyway... I can't find it. I ll take your word for it. I just remember I had to do the cursor dance (quite some time ago tho)
Hmm, looks like the main discussion happened somewhere else and it isn't linked in the tickets. The auto-commit : false
option was definitely part of the fallout from that and was key to making Postgres stream result sets apparently...
The auto-commit option on opening a connection is fairly new to java.jdbc
.