如何在 clojure.contrib.sql 中的结果集上调用 next() ?

发布于 2024-10-02 12:00:06 字数 549 浏览 0 评论 0原文

最初我想问为什么我在结果集上调用 (seq) 作为空性测试时遇到问题,但一些研究表明,这显然是因为 jdbc 光标没有移动到任何地方。很好,花花公子。如果我不知道结果集的名称,有没有办法在结果集上调用 next() ?我可以将它绑定到 clojure 中的符号,但我无法弄清楚如何从那里调用该方法。

编辑:如果不清楚,我指的是 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 的帮助,顺便说一句...haven'不过

,如果查询没有返回任何内容,使用 (seq) 会抛出 NullPointerException。我想知道是否有更干净、惯用的方法来做到这一点?

Originally I was going to ask why I was having problems calling (seq) on a result set as a test for emptiness, but a bit of research showed that it's apparently because the jdbc cursor hasn't moved anywhere. Fine and dandy. Is there a way to call next() on the resultset if I don't know its name? I can bind it to a symbol in clojure, but I haven't been able to figure out how to call the method from there.

edit: in case it's not clear, I'm referring to the java resultSet method next(), not the clojure (next)

edit#2 here's a code snippet:

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

(Thanks for the help on .next, btw...haven't done much java interop yet)

Still, though, using (seq) throws a NullPointerException if the query didn't return anything. I'm wondering if there's a cleaner, idiomatic way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一个人练习一个人 2024-10-09 12:00:06

res 将绑定到基于 ResultSet 的 Clojure 序列,其中每个项目都是结果记录的映射,其中输出列名称作为键中的关键字。您无法获取底层的实际 ResultSet 对象。

通常你根本不会再打电话。按照 Clojure 的习惯,您将利用对序列进行操作的庞大函数库(映射、过滤、归约等)来生成输出。在这里,您可能会说:

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

这会将 :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

res will be bound to a Clojure sequence based on the ResultSet where each item is a map of a result record with output column names as keywords in keys. You can't get to the underlying actual ResultSet object.

Typically you don't call next at all. To be idiomatic Clojure, you would utilize the vast library of functions that operate on sequences (map, filter, reduce, etc) to produce your output. Here you might say something like:

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

which would apply :guid as a function over the res seqeuence and retrieve the column value of guid in each record, returning you a new sequence of all the guids. You could then wrap that map in a filter or whatever else you needed.

In this case, seq should be what you want but I think the abstraction is leaking a bit. When I tried it I got java.sql.SQLRecoverableException: Closed Resultset: next which implies to me the ResultSet is being closed too early in the abstraction. However, I found empty? worked ok for this use case.

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

This seems like a bug in clojure.core/resultset-seq to me and I reported it here as CLJ-676.

不寐倦长更 2024-10-09 12:00:06

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

如果返回一行,则应该返回something,如果没有匹配的行,则应该返回nil

您之前的查询失败,因为 res 是调用 (resultset-seq x) 的值,因此您无法使用 Java 的 ResultSet.next() ,您也不想再次对其调用 seq

如前所述,您必须在 ResultSet (和 Connection)打开时评估 resultset-seq,因此您必须

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

How about

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

That should return something if a row is returned, or nil if there's no matching row.

Your earlier query was failing because res is the value of a call to (resultset-seq x), so you can't use Java's ResultSet.next() on it, nor do you want to call seq on it again.

As noted, you have to evaluate the resultset-seq while the ResultSet (and Connection) is open, so you would have to have

(defn users-with-email [email]
  (with-connection db
    (with-query-results res ["SELECT guid from users WHERE email=?" email]
      (doall res))))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文