I discovered that a simple program that reads a csv file and save it in a database is shorter in Clojure than in Java. I searched on google and on clojure apis to find out how can be done and this is my first Clojure useful project. This is how I've done it:
1. I used Oracle XE database, I created a user called clojuretest/clojurtest@XE and created a simple table country like this:
CREATE TABLE country (
country NVARCHAR2(20) NULL,
isocode NVARCHAR2(10) NULL
)
/
2. I installed Netbeans 6.8 with Enclojure plugin. I created a Clojure project and opened the REPL.
3. First I wanted to parse the csv file containing pairs of country and isocode without all the Java hassle.
I discovered that in Clojure is a special package for parsing stuff so I had to load in my REPL:
(use '(clojure.contrib duck-streams str-utils))
So after some googling around this is what I got:
(doseq [line (read-lines "D:\\clojure_test\\country.csv")]
(let [[x y ] (re-split #"," line)]
;(println line)
;(println x)
;(println y)
(println [x y ])
)
)
This means that each line of the country.csv is read by read-lines function and the vector [x y] will be populated with each value from csv columns.
So x will have a Afghanistan and y will have AFG.
And after each assignment I am printing the vector to see what we got.
4. Then I did some research of how to save it in the db.
For database stuff we need this package:
(use 'clojure.contrib.sql)
Then we need to declare our db connection:
(def db {:classname "oracle.jdbc.driver.OracleDriver" ; must be in classpath
:subprotocol "oracle:thin"
:subname "@localhost:1521"
; Any additional keys are passed to the driver
; as driver-specific properties.
:user "clojuretest"
:password "clojuretest" })
We need to define a insert function knowing the table name and column names of course:
(defn insert-db-entry
"Insert data into the table"
[country,isocode]
(clojure.contrib.sql/insert-values
:country
[:country :isocode]
[country isocode]))
5. We define a test function to see if It works:
(clojure.contrib.sql/with-connection
db
(clojure.contrib.sql/transaction
(insert-db-entry "Albania" "ALB") ))
If was ok will get a (-2) response in the REPL other wise an exception will occurr.
Actually this was all the hard work because for a strange reason clojure did not see my jdbc jars (ojdbc14.jar) even if they were in classpath.
So I added as libs in Netbeans project and restarted the IDE and it worked.
6. We actually write the code to do the inserts from the csv file in the db.
Note that I do a dummy insert , no ckecking, just to see that works.
(clojure.contrib.sql/with-connection
db
(clojure.contrib.sql/transaction
(doseq [line (read-lines "E:\\clojure_test\\country.csv")]
(let [[x y ] (re-split #"," line)]
(insert-db-entry x y)
)
)))
So instead of printlin the vector I could actually insert in db the x and y values!
It worked! Maybe now it's time to search how to do filters on the data...but next time.
