Clue Database Library

Topic: Clue Database Library

Due to size constraints, the Mosquito Virtual Machine can not include a wrapper for any of the full fledged relational databases, or even the simpler "dictionary" style databases, like DBM. These databases are often useful for application developers who are in a hurry, because they provide a way to manage complex data structures without taking the time to construct a data model and functionality required to search and update the model.

The "lib/clue" module provides a simple, efficient in-memory database built on top of MOSVM's set and dictionary types; this database can be easily saved and loaded from S-Expressions, and is type agnostic -- any value can be stored in a clue database.

We start with new-clue-db:

;; Import the database module.
>> (import "lib/clue")
;; Create a new Clue database.
>> (define db (new-clue-db))
:: [DB]
;; Insert a record.  The first argument to put-clue must always be the
;; database; subsequent terms may either be lists, in the form (key
;; value), or just a key in which case, the value is the default,
;; true.
>> (put-clue db (first-name "John") (last-name "Doe") customer)
:: [RECORD]
;; And another. Parameter order does not matter.
>> (put-clue db (last-name "Doe") (first-name "Jane") customer)
:: [RECORD]

As you may have realized, put-clue is a macro -- the database API makes extensive use of macros to provide an orthogonal query language; this is an example of how Lisp macros can be used to provide specialized dialects.

;; Clue does not require that all records in the database have an
;; identical number of fields.
>> (define c (put-clue db (last-name "Jones") (nick-name "A.J.") customer)

Each put-clue operation returns a single clue record object. This object contains a reference to the database that contains the record, and an association list containing all of the parameters assigned to the record so far. You may list all of the parameters associated with a record, with the get-clue macro.

;; What parameters does c, defined above, have?
>> (get-clue c)
:: ((last-name . "Jones") (nick-name "A.J.") (customer . #t))
;; More specifically, what is his last-name?
>> (get-clue c last-name)
:: "Jones"
;; What was his first name?
>> (get-clue c first-name)
:: #f
;; Right. First name was omitted. Nick name and last name?
>> (get-clue c nick-name last-name)
>> ("A.J." "Jones")
; Put it all together..
>> (define (customer-name record)
     (string-append (or (get-clue record nick-name)
                        (get-clue record first-name))
                    " "
                    (get-clue record last-name)))

Of course, a database is only as good as its search ability. The find-clue macro provides a simple query language that searches for the presence of a field, and the equivalence of a field to a given value. While this pales in comparison with any good relational database -- relational databases tend to have more than 200 lines of code in their implementation.

;; What records have the last name of Doe in our database?
>> (find-clue db (last-name "Doe"))
:: ([RECORD] [RECORD])
;; Well, that's not very useful. Perhaps an association list for each?
>> (get-clue (find-clue db (last-name "Doe")))
:: (((last-name . "Doe") (first-name "John") (customer . #t))
   ((last-name . "Doe") (first-name "Jane") (customer . #t)))
;; Just rubbing it in.. What are their first names?
>> (get-clue (find-clue db (last-name "Doe")) first-name)
:: ("John" "Jane")
;; First names of all our customers?
>> (get-clue (find-clue db customer) first-name)
:: ("John" "Jane" #f)
;; Uh-oh.. A.J., the non-conformist.. First names of all our customers
;; who have first names?
>> (get-clue (find-clue db customer first-name) first-name)
:: ("John" "Jane")

Our database language also provides functionality for adding and modifying properties for a record; set-clue will silently update the indexes employed by the database.

;; Ah, now we know why he doesn't like using his first name..
>> (set-clue (find-clue db (last-name "Jones"))
                          (first-name "Abraham"))
:: [RECORD]