2011-08-24 5 views
6

Solo intento comprender el propósito de open-global y with-results de clojureql. Comencé leyendo este resumen: How does ClojureQL compare to clojure.contrib.sql?clojureql, open-global y with-results

Pensé por algún motivo que open-global reemplazaría a sql/with-connection, por ej. Pensé que esto funcionaría:

(def db {...}) ; connection details omitted 
(open-global db) 

(println (:name (first @(table :users))) 

Sin embargo, esto no funciona. Parece que necesito hacer open-global y envolver la consulta de ejecución en un (sql/with-connection db), lo que me sorprendió (pensé que open-global proporcionaba una conexión predeterminada globalmente accesible). Entonces dado que ese no parece ser el caso, ahora me pregunto exactamente qué hace.

Además ... ¿cómo se diferencian los resultados de simplemente la ejecución de la consulta con @? Porque parece que @ (table: users) me dejará con una secuencia que es el resultado de ejecutar la consulta (¿no es lo que hace también with-results)?

Respuesta

3

La diferencia entre usar deref (el símbolo @) versus with-results es bastante sutil. Básicamente, ambos hacen lo mismo, siendo la única diferencia el momento en que se ejecuta realmente la consulta. Ambos son en realidad sólo contenedores para el método del protocolo Relationapply-on, aquí está el código para with-results:

(defmacro with-results 
    [[results tble] & body] 
    `(apply-on ~tble (fn [~results] [email protected]))) 

Y para deref:

(deref [this] 
    (apply-on this doall)) 

Como se puede ver deref es exactamente el mismo que:

(with-results [res (table :users)] (doall res)) 

Si mira la documentación doall, verá que es una función que se usa para caminar a través de una secuencia perezosa para forzar cualquier efecto secundario, el resultado es que la secuencia se evaluará por completo, por lo tanto, ya no es holgazana sino que reside en la memoria.

Para darle una explicación más realista, usando deref realmente ejecute la consulta en el momento en que se llama, mientras usa with-results la consulta se ejecutará perezosamente, es decir, cuando el resultado realmente se consuma.

En cuanto a open-global, tenías razón al respecto, realmente debería abrir una conexión disponible a nivel mundial que ClojureQL usará cuando no especifique una usando wiht-connection. El comportamiento que está observando probablemente sea un error, por lo que le sugiero que lo informe en el canal de IRC o en el rastreador de problemas de ClojureQL en Github. No he usado ClojureQL desde hace un tiempo, pero mirando el código, parece que se ha convertido a la utilización de clojure.java.jdbc en lugar de clojure.contrib.sql, algo podría haber ido mal allí.

+0

un poco más de información, en las pruebas He encontrado que si uso con resultados, entonces open-global funciona, pero si uso deref/@, entonces necesita conexión con conexión (y open-global, extrañamente ...) Verifico el irc, y gracias por la respuesta detallada! – Kevin