Transforming Your Database Records into a Usable Model
May 15th, 2008
I realize I haven’t written anything new here lately. I’ve been working on a bunch of pretty cool stuff that I really want to share and get in the open. Hopefully I’ll be writing more about the stuff I’ve been doing.
For database work, I’ve been using Jay McCarthy’s sqlite.plt library. If you’ve used this library at all, you’ll quickly realize that it returns results similar to this:
The common way to parse these records is by using match-let from the match.ss library. Using match-let every time you have to parse a result set can be a pain in the ass. I ended up writing a function that takes a result set like above and transforms it into a list of associative lists. So the above is transformed into:
Now instead of having to use match-let every time, all you have to do is pull the attributes you want by using assoc on each associative list. Since the result above is a list of associative lists, you’d have to iterate over the list and then use assoc. Assuming we only got one result back, it could look like this:
If I wanted to get the username attribute from this associative list, I could do
Not bad, eh? So, what’s the code to transform my records into a list of associative lists?
Granted, this code is kind of funny to look at. Let’s start at the end where I’m returning either res or (car res). If the length of the cdr of the vector list is 1, meaning the list of vectors is (#(”id” “username” “password”) #(”1″ “david” “batman”)) and its cdr is (#(”1″ “david” “batman”)), return the car of the result. If there are multiple records in the cdr of the vector list, return the result as is. The results in either case are associative lists. When the length of the cdr is 1, the resulting list will only have one associative list in it. When the length of the cdr is greater than 1, the resulting list will have multiple associative lists in it that you have to iterate over. Returning the car of the multiple associative lists will give you only the first associative list when you really want all of them.
I hope that makes at least a little sense.
The actual mapping of keys with values should hopefully be pretty straightforward. The inner map:
Returns an associative list where (car list-of-vecs) is #(”id” “username” “password”) and v is a result element in the form of #(”1″ “david” “batman”). The outer map passes that v element from each of the cdr of list-of-vecs, which could be (#(”1″ “david” “batman”) #(”2″ “foo” “bar”)) or similar. Also remember that functions you pass to map don’t necessarily have to take one argument. Like cons, you have to pass two arguments, so mapping cons to data requires two arguments. In this case, the two arguments are (vector->list (car list-of-vecs)) and (vector->list v).
I think that’s about it for this function. If anything is unclear or you have a better solution definitely feel free to leave me a comment.