nicferrier / emacs-db

very simple database for emacslisp, can also wrap other databases.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Emacs Db - Key/Values stores for Emacs

An EmacsLisp interface to key/value stores (Mongo, Postgresql Hstore, etc..) with a simple default implementation based on EmacsLisp Hashtables.

The interface

The idea behind this is to make an interface for interacting with simple key/value database stores that is portable across all such stores. So you can make code once but swap out the database with relative ease.

The interface includes the following functions:

db-make reference

Make a DB based on the reference.

db-get key db

Get the value from the db with the key.

db-put key value db

Put a new value into the db with the specified key.

Return the value as it has been put into the db.

db-map func db &optional query filter

Call func for every record in db optionally query filter.

query, if specified, should be a list of query terms.

func should take 2 arguments:

  key db-value

where the DB-VALUE is whatever the db has attached to the specified KEY.

This returns an alist of the KEY and the value the function returned. If filter is t then only pairs with a value are returned.

db-query db query

Do query on db and return the result.

This is db-map with an identity function.

Query language

db uses the query language provided by the kv library, which is implemented as a mapping function test on ever value by the persistent hashtable implementation.

The language should be translatable to just about any database query language (Mongo, SQL, etc...).

There are only 3 constructs currently, |, & and =.

An expression could be:

(= field-name value)

To select any record where field-name has the value

(|(= field-name value)(= other-field other-value))

To select any record where field-name has the value or other-field has the value other-value

(&(= field-name value)(= other-field other-value))

To select any record where field-name has the value and other-field has the value other-value.

Logical combinations of | and & are also possible.

Hashtable implementation

db comes with a simple implementation which can store any EmacsLisp object (though alists would most usually be preferred).

To make a db with the hash implementation:

(db-make 
  `(db-hash 
     :filename ,(format "/var/cache/some-file")))

Obviously, most often you will assign the db to a global variable.

(defvar my-db 
  (db-make 
   `(db-hash 
     :filename ,(format "/var/cache/some-file"))))

(db-put "001" '(("a" . 10)("b" . 20)) my-db)
(db-put "002" '(("a" . 17)("b" . "hello")("xyz" . "well!")) my-db)
(db-get "002" my-db)

results in:

(("a" . 17)("b" . "hello")("xyz" . "well!"))

Testing

Hash Db's are tied to filenames so to test them you often have to manage that persistence:

(unwind-protect
     (let ((mydb (db-make `(db-hash :filename "/tmp/mydb")))
           (json 
             (with-temp-buffer
              (insert-file-contents "~/work/elmarmalade/users-mongo.json")
              (goto-char (point-min))
              (json-read))))
       (--each json (db-put (car it) (cdr it) mydb))
       (list (db-get 'triss mydb)
             (db-get 'nicferrier mydb)))
  (delete-file "/tmp/mydb.elc"))

Note the deleting of the elc file. That's how the hash db is stored.

Alternately one could use fakir-file (see the fakir package) to mock the file system. But that's harder than just creating and throwing away the file.

About

very simple database for emacslisp, can also wrap other databases.


Languages

Language:Emacs Lisp 100.0%