[elephant-cvs] CVS elephant/src/elephant
ieslick
ieslick at common-lisp.net
Thu Mar 1 02:45:45 UTC 2007
Update of /project/elephant/cvsroot/elephant/src/elephant
In directory clnet:/tmp/cvs-serv19354
Added Files:
query-example.lisp query.lisp
Log Message:
Quick hack for object filtering queries; example of first pass at constraint syntax
--- /project/elephant/cvsroot/elephant/src/elephant/query-example.lisp 2007/03/01 02:45:45 NONE
+++ /project/elephant/cvsroot/elephant/src/elephant/query-example.lisp 2007/03/01 02:45:45 1.1
(in-package :elephant)
;; TEST DATA
(defparameter *constraint-spec*
'(:BDB "/Users/eslick/Work/db/constraint/"))
(defun print-name (inst)
(format t "Name: ~A~%" (slot-value inst 'name)))
(defpclass person ()
((name :initarg :name :index t)
(salary :initarg :salary :index t)
(department :initarg :dept)))
(defpclass department ()
((name :initarg :name)
(manager :initarg :manager)))
(defparameter *names*
'("Jacob"
"Emily"
"Michael"
"Emma"
"Joshua"
"Madison"
"Matthew"
"Abigail"
"Ethan"
"Olivia"
"Andrew"
"Isabella"
"Daniel"
"Hannah"
"Anthony"
"Samantha"
"Christopher"
"Ava"
"Joseph"
"Ashley"
))
(defun test-dataset ()
(let* ((greg (make-instance 'person :name "Greg" :salary 100000))
(sally (make-instance 'person :name "Sally" :salary 110000))
(mkt (make-instance 'department :name "Marketing" :manager greg))
(engr (make-instance 'department :name "Engineering" :manager sally)))
(setf (slot-value greg 'department) mkt)
(setf (slot-value sally 'department) engr)
(with-transaction ()
(loop for i from 0 upto 500 do
(make-instance 'person
:name (format nil "~A~A" (utils:random-element *names*) i)
:salary (floor (+ (* (random 1000) 150) 30000))
:department (if (= 1 (random 2)) mkt engr))))))
(defun print-person (person &optional (stream t))
(format stream "name: ~A salary: ~A dept: ~A~%"
(slot-value person 'name) (slot-value person 'salary)
(slot-value (slot-value person 'department) 'name)))
(defun example-query1 ()
"Performs a query against a single class. Trivial string & integer matchingA"
(map-class-query #'print-person
'((person name = "Greg")
(person salary >= 100000))))
(defun example-query2 (low-salary high-salary)
"Parameterized query"
(map-class-query #'print-person
`((person salary >= ,low-salary)
(person salary <= ,high-salary))))
--- /project/elephant/cvsroot/elephant/src/elephant/query.lisp 2007/03/01 02:45:45 NONE
+++ /project/elephant/cvsroot/elephant/src/elephant/query.lisp 2007/03/01 02:45:45 1.1
;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*-
;;;
;;; query.lisp -- Implement syntax for the elephant query engine
;;;
;;; Copyright (c) 2007 by Ian S. Eslick
;;; <ieslick at common-lisp.net>
;;;
;;; Elephant users are granted the rights to distribute and use this software
;;; as governed by the terms of the Lisp Limited General Public License
;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
;;;
(in-package :elephant)
(defparameter *string-relation-functions*
`((< . ,#'string<)
(< . ,#'string<=)
(> . ,#'string>)
(> . ,#'string>=)
(= . ,#'equal)
(!= . ,(lambda (x y) (not (equal x y))))))
(defparameter *number-relation-functions*
`((< . ,#'<)
(> . ,#'>)
(= . ,#'=)
(!= . ,#'(lambda (x y) (not (= x y))))))
(defun relation-string-function (rel)
(cdr (assoc rel *string-relation-functions*)))
(defun relation-number-function (rel)
(cdr (assoc rel *number-relation-functions*)))
(defun test-relation (rel ival tvals)
(assert (or (and (numberp ival) (numberp (first tvals)))
(and (stringp ival) (stringp (first tvals)))))
(typecase ival
(string (funcall (relation-string-function rel) ival (first tvals)))
(number (funcall (relation-number-function rel) ival (first tvals)))))
(defun get-query-instances (constraints)
(let ((list nil))
(flet ((collect (inst)
(push inst list)))
(declare (dynamic-extent collect))
(map-class-query #'collect constraints))))
(defun map-class-query (fn constraints)
"Map instances using the query constaints to filter objects, exploiting
slot indices (for last query) and stack allocated test closures"
(assert (not (null constraints)))
(destructuring-bind (class slot relation &rest values) (first constraints)
(flet ((filter-by-relation (inst)
(when (test-relation relation (slot-value inst slot) values)
(funcall fn inst))))
(declare (dynamic-extent filter-by-relation))
(if (null (cdr constraints))
(if (find-inverted-index class slot)
(if (= (length values) 1)
(progn
(map-class-index fn class slot (first values) (first values))
(map-class-index fn class slot (first values) (second values))))
(map-class #'filter-by-relation class))
(map-class-query #'filter-by-relation (cdr constraints))))))
;;
;; Conjunctions of indices
;;
;;(defun map-classes (fn classes)
;; (map-index-list fn (mapcar #'find-class-index classes)))
;;(defun map-index-list (fn indices)
;; (dolist (index indices)
;; (map-index fn index)))
More information about the Elephant-cvs
mailing list