Как вызвать next () для набора результатов в clojure.contrib.sql? - PullRequest
1 голос
/ 16 ноября 2010

Первоначально я собирался спросить, почему у меня возникли проблемы с вызовом (seq) набора результатов как теста на пустоту, но некоторые исследования показали, что это, очевидно, потому, что курсор jdbc никуда не перемещался.Прекрасно и модно.Есть ли способ вызвать next () в наборе результатов, если я не знаю его имени?Я могу связать его с символом в clojure, но я не смог выяснить, как вызвать метод оттуда.

edit: если неясно, я имею в виду java resultSetМетод next (), а не clojure (next)

edit # 2, вот фрагмент кода:

(defn user-exists? [email]
  (with-connection db
   (with-query-results res ["SELECT guid from users WHERE email=?" email]
    (.next res)
    (seq res))))

(Спасибо за помощь по .next, кстати ... нетеще много сделано для взаимодействия с Java)

Тем не менее, использование (seq) создает исключение NullPointerException, если запрос ничего не дал.Мне интересно, есть ли более чистый идиоматичный способ сделать это?

Ответы [ 2 ]

3 голосов
/ 17 ноября 2010

res будет привязан к последовательности Clojure на основе ResultSet, где каждый элемент является картой записи результата с именами выходных столбцов в качестве ключевых слов в ключах. Вы не можете добраться до основного фактического объекта ResultSet.

Обычно вы вообще не звоните дальше. Чтобы быть идиоматическим Clojure, вы должны использовать обширную библиотеку функций, которые работают с последовательностями (map, filter, Reduce и т. Д.), Чтобы получить ваш вывод. Здесь вы можете сказать что-то вроде:

(with-query-results res ["SELECT guid from users WHERE email=?" email]
  (map :guid res))

, которое применимо: guid как функция над последовательностью и извлекает значение столбца guid в каждой записи, возвращая вам новую последовательность всех направляющих. Затем вы можете обернуть эту карту в фильтр или что-то еще, что вам нужно.

В этом случае seq должно быть тем, что вы хотите, но я думаю, что абстракция немного просачивается. Когда я попробовал это, я получил java.sql.SQLRecoverableException: Closed Resultset: next , что подразумевает, что ResultSet закрывается слишком рано в абстракции. Тем не менее, я обнаружил, что empty? работает нормально для этого варианта использования.

(defn user-exists? [email]
  (with-connection db
   (with-query-results res ["SELECT guid from users WHERE email=?" email]
    (.next res)
    (not (empty? res)))))

Мне это кажется ошибкой в ​​clojure.core / resultset-seq, и я сообщил об этом здесь как CLJ-676 .

1 голос
/ 20 ноября 2010

Как насчет

(defn user-exists? [email]
  (with-connection db
    (with-query-results res ["SELECT guid from users WHERE email=?" email]
      (first res))))

Это должно вернуть что-то , если строка возвращена, или nil, если нет подходящей строки.

Ваш предыдущий запрос не удался, потому что res является значением вызова (resultset-seq x), поэтому вы не можете использовать ResultSet.next() Java для него и не хотите вызывать seq для него снова.

Как уже отмечалось, вы должны оценить resultset-seq, пока ResultSetConnection) открыты, поэтому вам нужно будет иметь

(defn users-with-email [email]
  (with-connection db
    (with-query-results res ["SELECT guid from users WHERE email=?" email]
      (doall res))))
...