2011-02-03 4 views
2

USDA 영양 데이터베이스 파일을 ASCII에서 sqlite 데이터베이스로 변환하는 프로그램을 작성 중입니다. 이 파일들에 대한 정보는 http://www.ars.usda.gov/Services/docs.htm?docid=8964에서 찾아 볼 수 있습니다.for 구문에서 SQL 연결에 어떤 현상이 있습니까?

그러나 아래 코드에서 변환을 수행하는 함수에 for 구조체를 입력하면 "sql 연결이 사라집니다".

user=> (convert) 
(convert) 
#<Conn [email protected]> 
((01001 0100 Butter, salted BUTTER,WITH SALT Y 0.0 6.38 4.27 8.79 3.87) 
java.lang.Exception: no current database connection 

그래서, 내 유일한에 println 명령 변환 - 식품 설명에 : 나는 변환 작업을 실행하면

(defn sanitize-field [field] 
    (cond 
    (= field "~~") "" 
    (= field "") 0 
    (and (.startsWith field "~") (.endsWith field "~")) 
     (.substring field 1 (- (.length field) 1)) 
    :default (try 
       (Double. field) 
       (catch NumberFormatException n 0.0)))) 


(defn field-separator [line] 
    (.split line "\\^")) 

(defn parse-file [file] 
    (map (fn [l] (map sanitize-field (field-separator l))) 
     (.split (slurp (.getCanonicalPath file)) "\r\n"))) 

(defn convert-food-description [source-dir] 
    (println (sql/connection)) 
    (for [entry (parse-file (File. source-dir "FOOD_DES.txt"))] 
    (do 
     (println entry) 
     (println (sql/connection)) 
     (sql/insert-rows "food_des" entry)))) 

(Class/forName "org.sqlite.JDBC") 
(def db {:classname "com.sqlite.JDBC" :subprotocol "sqlite" :subname "nutrition.sqlite"}) 

(defn convert [] 
    (sql/with-connection db 
    (convert-food-description (File. "/home/savanni/Downloads/nutrient_database")))) 

, 여기에 내가 무엇을 얻을 수 있습니다. 함수 시작이 바로 실행 된 직후 첫 번째 코드와 같이 with-connection 문을 사용하여 만든 연결을 출력합니다. 하지만 for 루프가 시작되면 데이터베이스에 삽입 할 첫 번째 데이터 행을 인쇄 한 다음 SQL 연결을 다시 인쇄하려고 할 때 예외를 throw합니다.

연결이 사라질 수있는 원인은 무엇입니까? 완전히 다른 일이 있습니까?

가 업데이트 : 여기에 SQL/기능 모두 모두 clojure.contrib.sql

답변

3

for은 게으르다. 연결된 핸들이 with-connection에 의해 열리고 닫히기 전에 forconvert-food-description입니다.

연결 핸들이 아직 작동 중일 때 평가해야합니다. 예를 들어 fordoseq으로 변경해보십시오.

user> (require '(clojure.contrib [sql :as sql])) 
nil 
user> (import 'org.sqlite.JDBC) 
org.sqlite.JDBC 
user> (def db {:classname "com.sqlite.JDBC" 
       :subprotocol "sqlite" 
       :subname "foo.sqlite"}) 
#'user/db 
user> (sql/with-connection db (sql/create-table "foo" ["val" "int"])) 
(0) 

;; Bad 
user> (defn foo [] 
     (sql/with-connection db 
      (for [x (range 10)] 
      (sql/insert-records "foo" {:val x})))) 
#'user/foo 
user> (foo) 
; Evaluation aborted. 
;;java.lang.Exception: no current database connection 

;; Good 
user> (defn foo [] 
     (sql/with-connection db 
      (doseq [x (range 10)] 
      (sql/insert-rows "foo" [x])))) 
#'user/foo 
user> (foo) 
nil 
+0

나는 지금 바보 같아 보인다. 나는 전에 게으름에 걸려 넘어 졌어. –

0

첫 번째에서 온, 당신의 (println (sql/connection)) 현재 연결이 인쇄되지 않습니다. 대신 새로운 것을 생성하고 인쇄합니다.

둘째는, 당신은이 열리지 연결을하지

(def db {:classname "com.sqlite.JDBC" :subprotocol "sqlite" :subname "nutrition.sqlite"})로 DB를 정의, 이것은 단지 연결에 대한 설명입니다.

세 번째로 db을 매개 변수로 사용하여 convert-food-description 메서드에 전달해야하며 실제 쿼리에 사용하십시오.

+0

데이터베이스는 with-connection으로 연 다음 * db *에 바인드됩니다. insert-values, insert-rows 및 create-table과 같은 함수는 do-prepared을 호출하며 * db *에 저장된 연결을 참조합니다. 따라서 db를 매개 변수로 전달하는 것은 도움이되지 않습니다. –

관련 문제