File: README.creole

package info (click to toggle)
emacs-db 0.0.6%2Bgit20140421.b3a423f-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 80 kB
  • sloc: lisp: 333; makefile: 2
file content (147 lines) | stat: -rw-r--r-- 3,695 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
= 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.