6 Stimmen

clojureql, open-global und with-results

Ich versuche gerade, den Zweck von clojureqls open-global und with-results zu verstehen. Ich begann mit dem Lesen dieser Übersicht: Was ist der Unterschied zwischen ClojureQL und clojure.contrib.sql?

Ich dachte aus irgendeinem Grund, dass open-global sql/with-connection ersetzen würde, z. B. dachte ich, dies würde funktionieren:

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

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

Das funktioniert jedoch nicht. Es scheint, dass ich sowohl open-global tun müssen und wrap die ausführende Abfrage in einem (sql/with-connection db), die Art von überrascht mich (ich dachte, open-global eine Standard global zugängliche Verbindung bereitgestellt). Da dies also nicht der Fall zu sein scheint, bin ich jetzt links fragen genau, was es tut.

Außerdem... wie unterscheidet sich with-results von der einfachen Ausführung der Abfrage mit @? Denn es scheint, dass @(table :users) mich mit einer Sequenz zurücklässt, die das Ergebnis der Ausführung der Abfrage ist (ist es nicht das, was with-results auch tut)?

3voto

Nicolas Buduroi Punkte 3509

Der Unterschied zwischen der Verwendung von deref (die @ Symbol) im Vergleich zu with-results ist recht subtil. Im Grunde tun beide das Gleiche, der einzige Unterschied besteht darin, zu welchem Zeitpunkt die Abfrage tatsächlich ausgeführt wird. Beide sind eigentlich nur Umhüllungen für die apply-on Methode der Relation Protokoll, hier der Code für with-results :

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

Und für deref :

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

Wie Sie sehen können deref ist genau dasselbe wie:

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

Wenn Sie sich doall Dokumentation sehen Sie, dass es sich um eine Funktion handelt, mit der eine träge Sequenz durchlaufen wird, um einen Nebeneffekt zu erzwingen. Das Ergebnis ist, dass die Sequenz vollständig ausgewertet wird und somit nicht mehr träge ist, sondern im Speicher verbleibt.

Um Ihnen also eine konkretere Erklärung zu geben, verwenden Sie deref die Abfrage tatsächlich in dem Moment ausführen, in dem sie aufgerufen wird, während bei with-results wird die Abfrage zeitverzögert ausgeführt, d. h. wenn das Ergebnis tatsächlich verbraucht wird.

In Bezug auf open-global Sie hatten Recht, es sollte wirklich eine global verfügbare Verbindung öffnen, die von ClojureQL verwendet wird, wenn nicht eine mit wiht-connection . Das Verhalten, das Sie beobachten, ist wahrscheinlich ein Fehler, daher schlage ich vor, dass Sie es im IRC-Kanal oder im ClojureQL Issue Tracker auf Github melden. Ich habe ClojureQL schon eine Weile nicht mehr benutzt, aber wenn ich mir den Code ansehe, scheint es so, als ob sie dazu übergegangen sind, folgendes zu benutzen clojure.java.jdbc anstelle von clojure.contrib.sql Da könnte etwas schief gelaufen sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X