Web Development with Clojure, Third Edition - Appendix 4 (Database Access) p. 395

Dmitri Sotnikov @dmitri and Scot Brown @svmbrown

Hi all,
I’m working through the Appendix 4 (Database Access) starting on p. 395 and there are a number of discrepancies with what’s in the book vs. what actually will execute. So I will document here as I make my way through.

On p. 397,

(def ds (jdbc/get-datasource
{:subprotocol “postgresql”
:subname “//localhost/reporting
:user “admin”
:password “admin”}))

In the preceding example, we’ve defined a connection for an instance of the
PostgreSQL database by specifying the database type using the :dbtype key and a name using the :dbname key.

The above did not work for me and I got this error:

error {
:cause Unknown dbtype: , and :classname not provided.
:data {:subprotocol postgresql, :subname //localhost/reporting, :user admin, :password admin}
:via
[{:type clojure.lang.Compiler$CompilerException

Notice that :dbtype & :dbname are not in the hashmap (as the error message indicates and the sentence in the book itself indicates we should be using) so using this hashmap works (I also had to remove the “//local/” prefix in the dbname.

(def ds (jdbc/get-datasource
{:dbtype “postgresql”
:dbname “reporting”
:user “admin”
:password “admin”}))

After executing, I get:

[#:next.jdbc{:update-count 0}]

which is what the book says we should get.

Dmitri Sotnikov @dmitri and Scot Brown @svmbrown

On p. 398, in the Selecting Records section,

db-examples.core=> (get-user “foo”)
nil

does not work because get-user requires 2 parameters. Hence, you need to invoke:

(get-user ds “foo”)
nil

Dmitri Sotnikov @dmitri and Scot Brown @svmbrown

On pp. 400-1, in the Transactions section, the with-transaction macro code updates the passwords for users bar & baz to foo.
However, when doing a get-user on these users, the text shows:

db-examples.core=> (get-user “bar”)
#:USERS{:ID “bar”, :PASS “fooz”}
db-examples.core=> (get-user “baz”)
#:USERS{:ID “baz”, :PASS “fooz”}

The password should be foo not fooz.

Also, the text says:

The [t-conn db] part of the macro creates a binding the same way a let statement does.

It should be:

The [t-conn ds] part …

Dmitri Sotnikov @dmitri and Scot Brown @svmbrown

In the Use HugSQL section (starting on pp. 401), I ran into several issues when executing:

(add-user! db {:id “hug” :pass “sql”})

on p. 403; It complained of not knowing anything about db.

I suspect the db being referred to here was defined on p. 398, but that seemed optional and I never executed it when I first when through this. Going back and trying it, I got an error about not being able to resolve PGPoolingDataSource which I didn’t bother looking into.

So just going ahead with the parameter map method, here is what I did:

Change db to ds so now I have:

(:require [db-examples.core :refer [ds]]

in hugsql.clj; you’ll also need to change this line to use ds instead of db:

(add-user! ds {:id “hug” :pass “sql”})

Now when re-trying, I ran into a different problem:

; db-spec jdbc:postgresql://127.0.0.1:5432/reporting is missing a required parameter

; Evaluation of file hugsql.clj failed: class clojure.lang.Compiler$CompilerException

Here’s what I did to get this to work:
In project.clj file, add this line:

[com.layerware/hugsql-adapter-next-jdbc “0.5.3”]

as another dependency

Then in hugsql.clj,
add this to the :require list

[hugsql.adapter.next-jdbc :as next-adapter]

and then replace this line:

(hugsql/def-db-fns “users.sql”)

with:

(hugsql/def-db-fns “users.sql” {:adapter (next-adapter/hugsql-adapter-next-jdbc)})

Now the

(add-user! ds {:id “hug” :pass “sql”})

should run successfully.


On p. 404, there’s a sentence:

Let’s add a new file called resources/find_user.sql

for which presumably, the find-users function was to be added, but the code chunk still says: db-examples/resources/users.sql
so that was confusing; Furthermore, what do we do with the find_user.sql file anyway? Do we need to use the def-db-fns function with it? That’s not shown. I just put the find-users function into the users.sql file we’ve been using all along.

Lastly, this line:

we’d use the with-db-transaction macro

should just be with-transaction macro; i.e., there is no db in the macro name

Dmitri Sotnikov @dmitri and Scot Brown @svmbrown

On P. 408, it says:

let’s start the REPL in this namespace and create the table

However, the creation of the table already happened earlier on p. 406, when we ran

lein run migrate

So the code that is being executed on p. 408 will insert the records into the already created table.

However, the code didn’t run because it didn’t know about sql/insert-multi! as it’s not in the require section of the core.clj file.
I just added:

[next.jdbc.sql :as sql]

to the top of the file to get this to run.

oh yeah that’s a good catch.

Thank you, @bmads_51 !

I was going through this appendix, trying out the examples. I spent hours trying to figure out what I missed – what I was doing wrong – and eventually figured out most of the things you reported on my own. I was making my own notes/corrections in my copy of the PDF and then thought about reporting them, saw the “errata” link and found my way here, where I see that you have already documented all of this.

Thanks again!