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.
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).
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
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.
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
The function dbm-fetch retrieves data from the database.
cl-user(7): (dbm-fetch *mydb* "1") "foo1"
The function dbm-close closes the connection to the database.
cl-user(8): (dbm-close *mydb*) 0
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>
cl-user(10): (dbm-fetch *mydb* "1") "foo1"
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
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
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
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
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.