NDBM Tutorial

Go to the tutorial main page.

NDBM is an API for maintaining key/content pairs in a database. The database is designed for quick access to relatively static information. The implementation itself comes from a library provided with your operating system. See your operating system's documentation for details on the limitations on the size of data that your implementation may impose. The documentation for the Allegro CL NDBM Module is in doc/ndbm.htm.

NDBM is not available on Windows nor on Allegro CL 6.2

Thus this tutorial will not work on Windows. NDBM is not available for Allegro CL 6.2 (and so this tutorial will not work with Allegro CL 6.2 Trial Edition on UNIX platforms like Linux, MacOS X, and FreeBSD).

Quick Start Tutorial

  1. Initial setup
  2. Creating a database
  3. Adding data to the database
  4. Retrieving data
  5. Closing the database
  6. Opening the database again
  7. Checking the data is still there
  8. Adding more data
  9. Get the first key and subsequent keys
  10. A macro for traversing databases
  11. Another macro for opening a database and closing it when done
  12. Deleting keys

1. Initial setup

Here is a simple example where we create a database, put some data in it, and retrieve the data.

First we load the ndbm module and (optionally) use the :dbi.ndbm package:

cl-user(2): (require :ndbm)
; Fast loading /usr/local/acl70/code/ndbm.fasl
;   Foreign loading /usr/local/acl70/code/ndbm_wrappers.so.
t
cl-user(3): (use-package :dbi.ndbm)
t

2. Creating a database

Now we create a database. This is done with the function dbm-open with the arguments :if-does-not-exist :create.

cl-user(4): (setf *mydb* (dbm-open "my-db"
                                   :if-does-not-exist :create
                                   :if-exists :append))
#<dbi.ndbm::ndbm @ #x55d7bfa>
cl-user(5): 

The file containing the data will be my-db in the current directory. You could specify a directory component when opening the database. If the database file already exists, the specified call to dbm-open will append to it (because of the arguments :if-exists :append. Specifying :if-exists :supersede, the existing file would be deleted and a new database file created.

3. Adding data to the database

The function dbm-store stores data in the database. The data should have a key and a value. Both must be strings or usb8 vectors (vectors with element type (unsigned-byte 8)). Here we specify the key "1" and the value "foo1":

cl-user(6): (dbm-store *mydb* "1" "foo1")
t

4. Retrieving data

The function dbm-fetch retrieves data from the database.

cl-user(7): (dbm-fetch *mydb* "1")
"foo1"

5. Closing the database

The function dbm-close closes the connection to the database.

cl-user(8): (dbm-close *mydb*)
0

6. Opening the database again

The function dbm-open again to re-open the database:

cl-user(9): (setf *mydb* (dbm-open "my-db"
                                   :if-does-not-exist :create
                                   :if-exists :append))
#<dbi.ndbm::ndbm @ #x56a7b31>

7. Checking the data is still there

cl-user(10): (dbm-fetch *mydb* "1")
"foo1"

8. Adding more data

cl-user(11): (defun stringify-num-to-english (number)
               (format nil "~R" number))
stringify-num-to-english
cl-user(12): (stringify-num-to-english 3)
"three"
cl-user(13): (dotimes (i 10)
               (dbm-store *mydb*
                          (princ-to-string i)
                          (stringify-num-to-english i)))
nil

9. Get the first key and subsequent keys

The function dbm-firstkey starts the traversal of the database. dbm-nextkey then gets the next key and then traverses the database. The function loop-thru-database-clumsy uses traversal to loop through the key/value pairs. (`Clumsy' because it does not iteslf open and close the database, as its counterpart loop-thru-database, defined below, does.)

Note you may see a different first key: which key is first is not determined in similar but distinct databases. Also, when the database is looped through, the key/values pairs may be in a different order than the order displayed here.

cl-user(14): (setf x (dbm-firstkey *mydb*))
"foo"
cl-user(15): (defun loop-thru-database-clumsy (db)
               (let ((key (dbm-firstkey db)))
                 (loop
                   (print key)
                   (if (null key) (return)
                     (setf key (dbm-nextkey db))))))
loop-thru-database-clumsy 
cl-user(16): (loop-thru-database-clumsy *mydb*)
"foo" 
"9" 
"8" 
"7" 
"6" 
"5" 
"4" 
"3" 
"2" 
"1" 
"0" 
nil 
nil

10. A macro for traversing databases

The macro with-dbm-iterator traverses the database (again, the order of the key/value pairs may be different from what you see if you run the code):

cl-user(17): (with-dbm-iterator (*mydb* key)
               (print key))
"foo" 
"9" 
"8" 
"7" 
"6" 
"5" 
"4" 
"3" 
"2" 
"1" 
"0" 
nil

11. Another macro for opening a database and closing it when done

The macro with-open-dbm opens a database, evaluates its body, and then closes the database. We define a new function loop-thru-database that takes care of opening and closing the database.

cl-user(18): (dbm-close *mydb*) ;; we close the databse
0
cl-user(19): (defun loop-thru-database (name)
               (with-open-dbm (db name :if-exists :append)
                 (with-dbm-iterator (db key)
                   (format t "~% ~a -> ~a" key (dbm-fetch db key)))))
loop-thru-database
cl-user(20): (loop-thru-database "my-db")

 foo -> 1
 9 -> nine
 8 -> eight
 7 -> seven
 6 -> six
 5 -> five
 4 -> four
 3 -> three
 2 -> two
 1 -> one
 0 -> zero
nil

12. Deleting keys

The function dbm-delete deletes key/value pairs. Here we use the with-open-dbm macro while we delete a key, and then use the loop-thru-database function defined above to show the key is gone:

cl-user(21): (with-open-dbm (db "my-db")
               (dbm-delete db "5"))
t
cl-user(22): (loop-thru-database "my-db")

 foo -> 1
 9 -> nine
 8 -> eight
 7 -> seven
 6 -> six
 4 -> four
 3 -> three
 2 -> two
 1 -> one
 0 -> zero
nil

;;  Note '5 -> five' is gone.

This is the end of the tutorial. Note we have left the database closed because we used the with-open-dbm macro in the last forms. Again, the documentation for the Allegro CL NDBM Module is in doc/ndbm.htm.

Go to the tutorial main page.