resultset-seq
, который возвращает with-query-results
, вероятно, уже настолько ленив, насколько вы собираетесь получить. Лень работает только до тех пор, пока ручка открыта, как ты сказал. Там нет никакого способа обойти это. Вы не можете читать из базы данных, если дескриптор базы данных закрыт.
Если вам необходимо выполнить ввод-вывод и сохранить данные после закрытия дескриптора, то откройте дескриптор, быстро отбейте его (победив лень), закройте дескриптор и поработайте с результатами позже. Если вы хотите перебрать некоторые данные, не сохраняя их все в памяти сразу, то откройте дескриптор, получите ленивый seq для данных, doseq
над ним, затем закройте дескриптор.
Итак, если вы хотите что-то сделать с каждой строкой (для побочных эффектов) и отбросить результаты, не сохраняя весь набор результатов в памяти, то вы можете сделать это:
(defn do-something-with-all-foo [f]
(let [sql "select * from foo"]
(with-connection *db*
(with-query-results res [sql]
(doseq [row res]
(f row))))))
user> (do-something-with-all-foo println)
{:id 1}
{:id 2}
{:id 3}
nil
;; transforming the data as you go
user> (do-something-with-all-foo #(println (assoc % :bar :baz)))
{:id 1, :bar :baz}
{:id 2, :bar :baz}
{:id 3, :bar :baz}
Если вы хотите, чтобы ваши данные зависали в течение длительного времени, то вы также можете отбросить все это, используя вышеописанную функцию read-all-foo
(таким образом, победив лень). Если вы хотите преобразовать данные, то map
поверх результатов после того, как вы все это получили. В этот момент все ваши данные будут в памяти, но сам вызов map
и ваши преобразования данных после выборки будут ленивыми.