GNU Guile prototype
authorJavier Sancho <jsf@jsancho.org>
Sat, 23 Jan 2016 06:08:45 +0000 (07:08 +0100)
committerJavier Sancho <jsf@jsancho.org>
Sat, 23 Jan 2016 06:08:45 +0000 (07:08 +0100)
src/bongodb.scm [new file with mode: 0644]

diff --git a/src/bongodb.scm b/src/bongodb.scm
new file mode 100644 (file)
index 0000000..c6b2571
--- /dev/null
@@ -0,0 +1,96 @@
+;;;
+;;; BongoDB, an embedded document-based engine
+;;; Copyright (C) 2016 by Javier Sancho Fernandez <jsf at jsancho dot org>
+;;;
+;;; This program is free software: you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation, either version 3 of the License, or
+;;; (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+(define-module (bongodb)
+  #:use-module (ice-9 receive)
+  #:use-module (ice-9 vlist)
+  #:use-module (srfi srfi-9)
+  #:use-module (srfi srfi-9 gnu))
+
+
+;;; Collection Definition
+
+(define-record-type collection
+  (make-collection-record table)
+  collection?
+  (table get-table))
+
+(define (make-collection)
+  (make-collection-record vlist-null))
+
+(set-record-type-printer! collection
+  (lambda (record port)
+    (format port
+           "#<collection with ~a documents>"
+           (vlist-length (get-table record)))))
+
+
+;;; Working with documents
+
+(define (format-document document)
+  "Return a vhash document ready to store in a collection"
+  (document-with-id
+   (cond ((vhash? document)
+         document)
+        (else
+         (alist->vhash document)))))
+
+(define (document-with-id document)
+  "Return always a document with an id"
+  (or (and (vhash-assoc '_id document)
+          document)
+      (vhash-cons '_id (gensym) document)))
+
+(define (insert col . documents)
+  "Insert documents into the collection and return the new collection"
+  (cond ((null? documents)
+        (values col '()))
+       (else
+        (let* ((document (format-document (car documents)))
+               (docid (cdr (vhash-assoc '_id document)))
+               (newcol (make-collection-record (vhash-cons docid document (get-table col)))))
+          (receive (rescol docids)
+              (apply insert (cons newcol (cdr documents)))
+            (values rescol (cons docid docids)))))))
+
+(define (find col filter)
+  "Query the collection and return the documents that match with filter"
+  (let ((table (get-table col)))
+    (vhash-fold
+     (lambda (key value result) (cons (vhash->alist value) result))
+     '()
+     table)))
+
+
+;;; Tools
+
+(define (vhash->alist vhash)
+  (vhash-fold-right
+   (lambda (key value result) (assoc-set! result key value))
+   '()
+   vhash))
+
+
+;;; Testing
+
+(define (sample-test)
+  (let ((col (make-collection)))
+    (format #t "1 New collection: ~a~%" col)
+    (set! col (insert col '((a . 1) (b . 2)) '((a . 10) (b . 20)) '((a . 1) (b . "hello world"))))
+    (format #t "2 Insert 3 documents: ~a~%" col)
+    (format #t "3 Search (a . 1): ~a~%" (find col '((a . 1))))))