2011-10-30 6 views
2

sqliteデータベースからメタデータを取得しようとしています。現時点での主な目的は、テーブルのリストを取得することでした。 (:linkここから):下記Clojure:データベースのメタデータを読み取る

コード

(defn db-get-tables 
"Demonstrate getting table info" 
[] 
(sql/with-connection db 
    (into [] 
     (resultset-seq 
     (-> (sql/connection) 
      (.getMetaData) 
      (.getTables nil nil nil (into-array ["TABLE" "VIEW"]))))))) 

これは私のデータベース内のテーブルに関するメタデータとマップのリストを提供します。私は(「の」または「最初」を使用して)このリストを反復処理しようとした場合しかし、それは私に与える:

"Don't know how to create ISeq from proj00.operations.database$tables-list" 

を私はこれを行う簡単な方法がなければならないと考えています。しかし、私はちょうどWeb上で適切な情報を見つけることができません。また、そのエラーがどこから来ているのか理解できません。

答えて

4

データベースとの接続が「sql/with connection db」の範囲内でのみ開かれている可能性があります。このようなコレクションをMicrosoft SQLで繰り返し処理すると、接続が閉じられているというエラーが表示されます。

doetallでresultset-seqをラップする場合、これは修正する必要があります。これは、すべての結果をメモリに入れ、接続を閉じることができるようにするために、怠惰を打ち破ります。あなたが怠け者であることを保つには、 "接続された"スコープ内に反復を置くべきですが、完了するまで接続を開いたままにしておきます。今、あなたが持つメタデータを呼び出すことができますので、

(defmacro get-sql-metadata [db method & args] 
    `(with-connection 
    ~db 
    (doall 
     (resultset-seq 
     (~method 
      (.getMetaData (connection)) 
      [email protected]))))) 

:また

、あなたは(私の質問にVerneriÅbergの答えのおかげで)このマクロを作ることによって、すべてのメタデータ・メソッドをサポートするには、この機能を一般化することができますメタデータの方法などのような、独自のパラメータ:

(get-sql-metadata db .getTables nil nil nil (into-array ["TABLE" "VIEW"])) 
or 
(get-sql-metadata db .getColumns nil nil nil nil) 

フォロー: が接続testdatabaseを作成し、すべてのものはこのように動作するはずです。

Leiningenを

(defproject sqlitetest "1.0.0-SNAPSHOT" 
    :description "FIXME: write description" 
    :dependencies [[org.clojure/clojure "1.3.0"] 
        [org.xerial/sqlite-jdbc "3.6.16"] 
        [org.clojure/java.jdbc "0.1.0"]]) 

プログラム

(ns sqlitetest 
    (:use [clojure.java.jdbc])) 

(def db { :classname "org.sqlite.JDBC" 
      :subprotocol "sqlite" 
      :subname "E:/temp/chinook.db"}) 

(defmacro get-sql-metadata [db method & args] 
    `(with-connection 
    ~db 
    (doall 
     (resultset-seq 
     (~method 
      (.getMetaData (connection)) 
      [email protected]))))) 

(def tables-list 
    (get-sql-metadata db .getTables nil nil nil (into-array ["TABLE" "VIEW"]))) 

REPL

sqlitetest=>(map :table_name tables-list) 
("SQLITE_SEQUENCE" "ALBUM" "ARTIST" "CUSTOMER" "EMPLOYEE" "GENRE" "INVOICE" "INVOICELINE" "MEDIATYPE" "PLAYLIST" "PLAYLISTTRACK" "TRACK") 

sqlitetest=>(first tables-list) 
{:self_referencing_col_name nil, :table_name "SQLITE_SEQUENCE", :type_schem nil, :ref_generation nil, :table_type "TABLE", :table_schem nil, :table_cat nil, :type_cat nil, :type_name nil, :remarks nil} 

コメントの備考とエラーがDEFN代わりにDEFを行うことによって引き起こされ の質問に答えますタブーの上にあなたのコメントのように電子リスト。 defnを使用すると同じエラーが発生します。

+0

ありがとうNielsk、偉大な助け。しかし、私はdefnでマクロ呼び出しをラップすると同じミスを抱えています: (defn tables-list [] (get-sql-metadata db .getTables nil nil nil(into配列["TABLE" "VIEW "]))) – kfk

+0

パーフェクト。説明してくれてありがとう、私はそれらの概念にはかなり新しいです。 – kfk

+0

ここにも同じですが、それでも私の頭の中を掴みようとしています..助けになるのはうれしいです!ああ、答えが正しい場合は、緑色のチェックマークでマークすることができます:) – NielsK

関連する問題