chickadee » mdh


An interface to a Multidimensional Hierarchical database. This egg includes code from the open source MUMPS system available at It provides a simple and efficient interface to a persistent file-based database of arbitrary size. The database can also be seen as a tree and can be traversed and inspected.

See also the MDH programming guide for a more detailed look. This egg just provides a Scheme layer on top of the MDH C++ API.


(import mdh)

Programming interface

Access to the database is done through "globals", named entities stored in the database, with an optional list of indexes specifiying multi-dimensional arrays. Up to 10 dimensions can be given.

global GLOBALprocedure

Allocates a reference to a global persistent variable. The reference should be freed using `global-free` when it is no longer required. There may be multiple references to the same global variable at the same time in existance. GLOBAL may be a string, symbol or number and will be converted to a string. The result of this a wrapper procedure, invoking this object with a (possibly empty) set of indices is equivalent to calling global-ref:

(define g (global "foo"))

(global-set! g 123)
(global-ref g) => "123"
(g)            => "123"

A wrapper procedure also has a SRFI-17 setter procedure:

(set! (g 1 2) "xxx")
(g 1 2) => "xxx"
global-object Xprocedure

Returns the object reference contained in the wrapper procedure G.

global? Xprocedure

Returns true if X is a global object record structure instance.

global-set! G VALUE INDEX ...procedure

Sets the value of the element of G represented by the given indices to VAL. VAL will be converted to a string before it is stored. INDEX may be a string, symbol or number and will also be converted to string. If the element doesn't exist yet for G, then it is created.

global-ref G INDEX ...procedure

Returns the value of global G at the given index. If no element exists at that position, then the empty string is returned.

global-count G INDEX ...procedure

Returns the number of descendants of the node specified by the global variable and indices.

global-free Gprocedure

Releases the storage required for the global G. After using this procedure, referencing the database through G will signal an error.

global-kill G INDEX ...procedure

Removes the given element and all its descendants from the database.

global-next G INDEX ...procedure

Returns the next index for the last item addressed by the given indices. Pass the empty string as the final index if you want to obtain the first valid index holding data. If no further index is defined, returns the empty string:

(define g (global-object (global "foo")))
(global-set! g "a" 1)
(global-set! g "b" 2)
(global-next g "")      => "1"
(global-next g "1")     => "w"
(global-next g "2")     => ""
global-previous G INDEX ...procedure

Similar to global-next but retrieves the previous index.

global-data G INDEX ...procedure

Returns a symbol or #f identifying the type of node addressed by the global G and the given indices.

  • #f: element is undefined
  • leaf: element has a value and no descendants
  • empty: element has no value but has descendants
  • branch: element has a value and descendants
global-merge G1 INDICES1 G2 INDICES2procedure

Copies the element and all its descendants given by G2 and the list of indices INDICES2 to the position identified by G1 and INDICES1.

^ NAME INDEX ...procedure

Creates a temporary global reference for NAME and returns its value using global-ref. NAME may be a global object, a global wrapper procedure or a name that is converted to a string.

(set! (^ NAME INDEX ...) VALUE)setter

Equivalent to (global-set! (global NAME) VALUE INDEX ...) but takes care to free the wrapper object of the global reference properly after assigning the value. NAME may be a global object, a global wrapper procedure or a name that is converted to a string.

^order NAME INDEX ...procedure
^data NAME INDEX ...procedure
^next NAME INDEX ...procedure
^previous NAME INDEX ...procedure
^count NAME INDEX ...procedure
^kill NAME INDEX ...procedure

These are all convenience procedures that perform the named operation with an existing global object or a temporarily allocated global reference if NAME is not a global wrapper or object.


Flushes any unwritten operations to the database and commits all pending operations.


Performs a flush-globals and closes all access to the database. This procedure is called automatically on normal or abnormal exit of the process. Also see "Caveats", below.


It is crucial to properly flush or close the database on exit or the file holding the persistent data may be incomplete or corrupted. For normal exit this is taken care of by setting [implicit-]exit-handler and handling the case when the process terminates with an error. When signals cause a process abort then code wanting to properly close the database must invoke flush-globals or close-globals explicitly.

Stored values and index strings can be at most 10000 bytes long.

More than 10 dimensions are currently not supported.


The original MDH database is maintained by Kevin O'Kane, see also the AUTHORS file in the egg distribution.

This egg was written and is maintained by Felix Winkelmann, using a subset of the original MDH source code. Many thanks to Luke K for the inspiration to create this egg and for providing helpful comments and suggestions.


This egg is hosted on the CHICKEN Subversion repository:

If you want to check out the source code repository of this egg and you are not familiar with Subversion, see this page.

Version history

Initial release


GNU General Public License

Contents »