com/github/kyleburton/sandbox/mdb.clj

Line Coverage Rate: 0.0
     Lines Covered: 0
Branch Coverage Rate: 0.0
    Branches Covered: 0
1(ns com.github.kyleburton.sandbox.mdb
2  (:import (com.healthmarketscience.jackcess 
3            Database TableBuilder
4            ColumnBuilder DataType Table)
5           (java.io File))
6  (:require [com.github.kyleburton.sandbox.utils :as kutils]
7            [clojure.contrib.duck-streams :as ds]
8            [clojure.contrib.str-utils :as str]))
9
10(defn new-col [name type]
11 (let [cb (ColumnBuilder. name)]
12   (.setSQLType cb (.getSQLType type))
13   (.toColumn cb)))
14
15(defmacro with-database [[var location] & body]
16  `(let [location# (ds/file (str ~location))
17         exists# (.exists location#)]
18     (with-open [~var (if exists#
19                        (Database/open location#)
20                        (Database/create location#))]
21       (let [res# (do ~@body)]
22         (.flush ~var)
23         res#))))
24
25(defn- ->safe-name [thing]
26  (.replaceAll
27   (cond (keyword? thing)
28         (.substring (str thing) 1)
29         (string? thing)
30         thing
31         true
32         (str thing))
33   "[^a-zA-Z0-9]" "_"))
34
35(defn create-table [#^Database db #^String table-name & cols]
36  (let [builder (TableBuilder. table-name)]
37    (loop [[[name type] & cols] (partition 2 cols)]
38      (if name
39        (do
40          (.addColumn builder (new-col (->safe-name name) type))
41          (recur cols))))
42    (.toTable builder db)))
43
44(defn create-or-get-table [#^Database db #^String table-name & cols]
45  (if (.contains (.getTableNames db)
46                 table-name)
47    (.getTable db table-name)
48    (apply create-table db table-name cols)))
49
50
51;; (kutils/doc-class
52;;  (with-database [db (kutils/$HOME "test.mdb")]
53;;    (.getTableNames db)))
54
55
56(defn insert-row [tbl & fields]
57  (.addRow tbl (to-array fields)))
58
59;; (class  (with-database [db (kutils/$HOME "test.mdb")] db))
60
61(defn row->seq [cols row]
62  (map #(get row (.getName %)) cols))
63
64(defn for-each-row 
65  ([#^Table tbl fn]
66     (let [cols (.getColumns tbl)]
67       (.reset tbl)
68       (loop [row (.getNextRow tbl)]
69         (if row
70           (do
71             (fn (row->seq cols row))
72             (recur (.getNextRow tbl)))))))
73  ([#^Database db #^String tbl fn]
74     (for-each-row (.getTable db tbl) fn)))
75
76(defn table->tab-file
77  [#^String mdb-file #^String table-name #^String tab-file]
78  (with-database [db mdb-file]
79    (with-open [out (ds/writer tab-file)]
80      (binding [*out* out]
81        (for-each-row 
82         db 
83         table-name
84         (fn [row]
85           (println (str/str-join "\t" row))))))))
86
87
88(defn- ->map [m]
89  (reduce (fn [r k]
90            (assoc r (keyword (.toLowerCase k)) (.get m k)))
91          {}
92          (keys m)))
93
94;; (with-database [db (kutils/$HOME "test.mdb")]
95;;    (prn (format "tables: %s" (.getTableNames db)))
96;;    (let [tbl (create-or-get-table
97;;               db 
98;;               "TABLE_A"
99;;               :id    DataType/INT
100;;               :fname DataType/TEXT
101;;               :lname DataType/TEXT
102;;               :addr1 DataType/TEXT
103;;               :addr2 DataType/TEXT
104;;               :city  DataType/TEXT
105;;               :state DataType/TEXT
106;;               :zip   DataType/TEXT)]
107;;      (insert-row tbl 1 "Kyle" "Burton" "2700 Horizon Drive" "STE 200" "King of Prussia" "PA" "19401")
108;;      (insert-row tbl 1 "Kyle" "Burton" "625 W. Rdige Pike" "STE 400" "Conshohocken" "PA" "19401")
109;;      (insert-row tbl 1 "Kyle" "Burton" "123 Main St" ""  "Wayne" "PA" "19401")))
110
111(defn mdb->tables [mdb]
112  (with-database [db mdb]
113    (seq (.getTableNames db))))
114
115;; (mdb->tables (kutils/$HOME "test.mdb"))
116
117
118;; (table->tab-file
119;;  (kutils/$HOME "test.mdb")
120;;  "TABLE_A"
121;;  (kutils/$HOME "table_a.tab"))
122
123(defn tab-file->table [mdb table file]
124  (with-database [db mdb]
125    (.importFile db table (ds/file file) "\t")))
126
127;; (tab-file->table (kutils/$HOME "test.mdb")
128;;                  "TABLE_B"
129;;                  (kutils/$HOME "table_a.tab"))
130
131(defn display-table [mdb tbl]
132  (with-database [db mdb]
133    (.display (.getTable db tbl))))
134
135;; (print (display-table (kutils/$HOME "test.mdb") "TABLE_A"))
136
137;; (with-database [db (kutils/$HOME "test.mdb")]
138;;    (prn (format "tables: %s" (.getTableNames db)))
139;;    (let [tbl (.getTable db "TABLE_A")]
140;;      (prn (format "columns[%s]: %s"
141;;                   (.getName tbl)
142;;                   (map #(.getName %) (seq (.getColumns tbl)))))
143;;      (do
144;;        (.reset tbl)
145;;        (loop [row (.getNextRow tbl)]
146;;          (if row
147;;            (do
148;;              (prn (format "row: %s" row))
149;;              ;(prn (format "     %s" (->map row)))
150;;              ;(prn (format "     id: %s" (:id (->map row))))
151;;              (recur (.getNextRow tbl))))))))
152
153(defmulti truncate-table (fn [& args] (map class args)))
154
155(defmethod truncate-table [String String] [mdb table]
156  (prn "S,S; opening db and delegating")
157  (with-database [db mdb]
158    (truncate-table db table)))
159
160(defmethod truncate-table [File String] [mdb table]
161  (prn "F,S; opening db and delegating")
162  (with-database [db mdb]
163    (truncate-table db table)))
164
165(defmethod truncate-table [Database String] [db table]
166  (prn "D,S; getting table and delegating")
167  (truncate-table db (.getTable db table)))
168
169;; probably faster to drop/create the table...but I don't see how to
170;; delete a table in the api?  deleteCurrentRow doesn't seem to
171;; work...
172(defmethod truncate-table  [Database Table] [db table]
173  (prn "D,T; rubber meets the road")
174  (.reset table)
175  (loop [row (.getNextRow table)]
176    (prn "in loop, row:" row)
177    (if row
178      (do
179        (prn "deleting row: " row)
180        (.deleteCurrentRow table)
181        (recur (.getNextRow table))))))
182
183
184;; (mdb->tables (kutils/$HOME "tmp" "test.mdb"))
185;; (truncate-table (kutils/$HOME "tmp" "test.mdb") "TABLE_B")
186
187;; (print (display-table (kutils/$HOME "test.mdb") "TABLE_A"))
188;; (print (display-table (kutils/$HOME "test.mdb") "TABLE_B"))
189
190;; (with-database [db (kutils/$HOME "test.mdb")]
191;;   (for-each-row db "TABLE_B" 
192;;                 (fn [row] (prn "row=" row))))
193