[elephant-cvs] CVS elephant/src/db-clsql

ieslick ieslick at common-lisp.net
Sun Feb 19 20:06:03 UTC 2006


Update of /project/elephant/cvsroot/elephant/src/db-clsql
In directory common-lisp:/tmp/cvs-serv14267/src/db-clsql

Modified Files:
	sql-collections.lisp sql-controller.lisp 
Log Message:
Includes most SQL fixes - works under SBCL/ACL.  Two problems remain in indexing under SQL for both SBCL/ACL

--- /project/elephant/cvsroot/elephant/src/db-clsql/sql-collections.lisp	2006/02/19 16:22:40	1.2
+++ /project/elephant/cvsroot/elephant/src/db-clsql/sql-collections.lisp	2006/02/19 20:06:03	1.3
@@ -19,11 +19,6 @@
 
 (in-package "ELEPHANT-CLSQL")
 
-(defclass sql-btree-index (btree-index sql-btree)
-  ()
-  (:metaclass persistent-metaclass)
-  (:documentation "A SQL-based BTree supports secondary indices."))
-
 (defmethod get-value (key (bt sql-btree-index))
   "Get the value in the primary DB from a secondary key."
   (declare (optimize (speed 3)))
@@ -234,6 +229,7 @@
       (progn
 	(multiple-value-bind (h k v)
 	    (cursor-next cursor)
+	  (declare (ignore h v))
 	  (when (my-generic-less-than key k)
 	    (setf vs t))
 	  )
@@ -285,7 +281,8 @@
   "Put by cursor.  Not particularly useful since primaries
 don't support duplicates.  Currently doesn't properly move
 the cursor."
-  (declare (optimize (speed 3)))
+  (declare (optimize (speed 3))
+	   (ignore key value key-specified-p))
   (error "Puts on sql-cursors are not yet implemented, because I can't get them to work on BDB cursors!"))
 
 ;; Secondary Cursors
@@ -451,7 +448,7 @@
 	  (remove-kv p (primary (cursor-btree cursor)))
 	  (let ((ck (:sql-crsr-ck cursor))
 		(dp (:dp-nmbr cursor)))
-
+	    (declare (ignorable dp))
 	    (cursor-next cursor)
 ;; Now that we point to the old slot, remove the old slot from the array...
 	    (setf (:sql-crsr-ks cursor)
@@ -466,20 +463,20 @@
 (defmethod cursor-get-both ((cursor sql-secondary-cursor) key value)
   "cursor-get-both not implemented for secondary indices.
 Use cursor-pget-both."
-  (declare (ignore cursor key value))
+  (declare (ignore key value))
   (error "cursor-get-both not implemented on secondary
 indices.  Use cursor-pget-both."))
 
 (defmethod cursor-get-both-range ((cursor sql-secondary-cursor) key value)
   "cursor-get-both-range not implemented for secondary indices.
 Use cursor-pget-both-range."
-  (declare (ignore cursor key value))
+  (declare (ignore key value))
   (error "cursor-get-both-range not implemented on secondary indices.  Use cursor-pget-both-range."))
 
 (defmethod cursor-put ((cursor sql-secondary-cursor) value &rest rest)
   "Puts are forbidden on secondary indices.  Try adding to
 the primary."
-  (declare (ignore rest value cursor))
+  (declare (ignore rest value))
   (error "Puts are forbidden on secondary indices.  Try adding to the primary."))
 
 
--- /project/elephant/cvsroot/elephant/src/db-clsql/sql-controller.lisp	2006/02/19 16:22:40	1.3
+++ /project/elephant/cvsroot/elephant/src/db-clsql/sql-controller.lisp	2006/02/19 20:06:03	1.4
@@ -26,91 +26,75 @@
 
 ;;; other clsql packages would have to be added for 
 ;;; non-postgresql databases, see the CL-SQL documentation
-(eval-when (:compile-toplevel :load-toplevel)
-  ;; NOTE: Integrate into load process
-  ;; Probably must be customized ... see documentation on installin postgres.
-  (defvar *clsql-foreign-lib-path* "/usr/lib")
-  (clsql:push-library-path *clsql-foreign-lib-path*)
-  (clsql:push-library-path *elephant-lib-path*))
+;; (eval-when (:compile-toplevel :load-toplevel)
+;;   ;; NOTE: Integrate into load process
+;;   ;; Probably must be customized ... see documentation on installin postgres.
+;;   (defvar *clsql-foreign-lib-path* "/usr/lib")
+;;   (clsql:push-library-path *clsql-foreign-lib-path*)
+;;   (clsql:push-library-path *elephant-lib-path*))
+
+
+;;
+;; The main SQL Controller Class
+;;
+
 
 (defclass sql-store-controller (store-controller)
-  ((dbonnection-spec :type list :accessor :dbcn-spc :initarg :dbconnection-spec
-		     ;; for postgres, this is host, db, user, password
-		     ;; If you can't get the lisp system to connect with 
-		     ;; this default information, make sure you can connect 
-		     ;; to the database called "test" under the user postgress 
-		     ;; with the psql console first.  Then study the authorization
-		     ;; and configuration files.
-		     :initform '("localhost.localdomain" "test" "postgres" ""))
-   (db :accessor controller-db :initarg :db :initform nil))
+  ((db :accessor controller-db :initarg :db :initform nil))
   (:documentation  "Class of objects responsible for the
     book-keeping of holding DB handles, the cache, table
     creation, counters, locks, the root (for garbage collection,)
     et cetera.  This is the Postgresql-specific subclass of store-controller."))
 
-(defmethod build-btree ((sc sql-store-controller))
-  (make-sql-btree sc))
+(eval-when (:compile-toplevel :load-toplevel)
+  (register-backend-con-init :clsql 'sql-test-and-construct))
+
+(defun sql-test-and-construct (spec)
+  "Entry function for making SQL backend controllers"
+  (if (sql-store-spec-p spec)
+      (make-instance 'sql-store-controller 
+		     :spec (if spec spec
+			       '("localhost.localdomain" "test" "postgres" "")))
+      (error (format nil "uninterpretable path/spec specifier: ~A" spec))))
 
 (defun sql-store-spec-p (spec)
   (and (listp spec)
        (eq (first spec) :clsql)))
 
-(defun sql-test-and-construct (spec)
-  (if (sql-store-spec-p spec)
-      (open-store-sql spec)
-      nil))
-
-(eval-when (:load-toplevel)
-  (register-backend-con-init :clsql 'sql-test-and-construct))
+;;
+;; Controller Indices
+;;
 
-(defmacro with-open-store-sql ((spec) &body body)
-  "Executes the body with an open controller,
-unconditionally closing the controller on exit."
-  `(let ((*store-controller* 
-	  (make-instance 'sql-store-controller :dbconnection-spec ,spec)))
-     (declare (special *store-controller*))
-     (open-controller *store-controller*)
-     (unwind-protect
-	  (progn , at body)
-       (close-controller *store-controller*))))
-
-(defun open-store-sql (spec  &key (recover nil)
-		       (recover-fatal nil) (thread t))
-  "Conveniently open a store controller."
-  (setq *store-controller*  
-	(if (sql-store-spec-p spec)
-	    (make-instance 'sql-store-controller :dbconnection-spec spec)
-	    (error (format nil "uninterpretable path/spec specifier: ~A" spec)))
-	)
-  (open-controller *store-controller* :recover recover 
-		   :recover-fatal recover-fatal :thread thread)
-  )
 
 ;; When you build one of these, you have to put in the connection spec.
-(defclass sql-btree (btree) 
-  (
-   )
+(defclass sql-btree (btree) ()
   (:documentation "A SQL implementation of a BTree"))
 
+(defmethod build-btree ((sc sql-store-controller))
+  (make-instance 'sql-btree :sc sc)
+  )
+
 (defmethod get-value (key (bt sql-btree))
   (let* ((sc (get-con bt))
 	 (con (controller-db sc)))
-    (sql-get-from-clcn (oid bt) key sc con)))
-	 
+    (sql-get-from-clcn (oid bt) key sc con)
+    )
+  )
 
-(defmethod existsp (key (bt sql-btree))
+(defmethod (setf get-value) (value key (bt sql-btree))
   (let* ((sc (get-con bt))
 	 (con (controller-db sc)))
-    (sql-from-clcn-existsp (oid bt) key  con)
+    (sql-add-to-clcn (oid bt) key value sc con)
     )
   )
 
-(defmethod (setf get-value) (value key (bt sql-btree))
+(defmethod existsp (key (bt sql-btree))
   (let* ((sc (get-con bt))
 	 (con (controller-db sc)))
-    (sql-add-to-clcn (oid bt) key value sc con)
+    (sql-from-clcn-existsp (oid bt) key  con)
     )
   )
+
 (defmethod remove-kv (key (bt sql-btree))
   (let* ((sc (get-con bt))
 	 (con (controller-db sc)))
@@ -125,40 +109,47 @@
 ;; directly into the class above.  I am not sure how best to
 ;; handle this problem.
 (defclass sql-indexed-btree (indexed-btree sql-btree )
-  (
-   (indices :accessor indices :initform (make-hash-table)
-	    )
+  ((indices :accessor indices :initform (make-hash-table))
    (indices-cache :accessor indices-cache :initform (make-hash-table)
-		  :transient t)
-   )
+		  :transient t))
   (:metaclass persistent-metaclass)
   (:documentation "A SQL-based BTree that supports secondary indices."))
 
+(defmethod shared-initialize :after ((instance sql-indexed-btree) slot-names
+				     &rest rest)
+  (declare (ignore slot-names rest))
+  (setf (indices-cache instance) (indices instance)))
+
 (defmethod build-indexed-btree ((sc sql-store-controller))
-  (let ((bt (make-instance 'sql-indexed-btree :sc sc)))
-    (setf (:dbcn-spc-pst bt) (:dbcn-spc sc))
-    bt
-    ))
+  (make-instance 'sql-indexed-btree :sc sc))
 
 (defmethod build-btree-index ((sc sql-store-controller) &key primary key-form)
-  (let ((bt (make-instance 'sql-btree-index :primary primary :key-form key-form :sc sc)))
-    (setf (:dbcn-spc-pst bt) (:dbcn-spc sc))
-    bt
-    ))
+  (make-instance 'sql-btree-index :primary primary :key-form key-form :sc sc))
 
 
-;; I need some way to get to the store-controller here...
-;; I could be the store controller in the hash table, that's probably
-;; the simplest thing to do..
+;; ISE NOTE: Much of the index management functionality is common between 
+;; bdb and sql - we could lift this along with indices and indices-cache 
+;; up to the main elephant code base and introduce a new update-index 
+;; generic function to handle the backend specific method for updating
+(defmethod map-indices (fn (bt sql-indexed-btree))
+  (maphash fn (indices-cache bt)))
+
+(defmethod get-index ((bt sql-indexed-btree) index-name)
+  (gethash index-name (indices-cache bt)))
+
+(defmethod remove-index ((bt sql-indexed-btree) index-name)
+  (remhash index-name (indices-cache bt))
+  (let ((indices (indices bt)))
+    (remhash index-name indices)
+    (setf (indices bt) indices)))
+
 (defmethod add-index ((bt sql-indexed-btree) &key index-name key-form populate)
   (let* ((sc (get-con bt))
-	(con (controller-db sc)))
+	 (con (controller-db sc)))
     (if (and (not (null index-name))
 	     (symbolp index-name) (or (symbolp key-form) (listp key-form)))
 	(let ((indices (indices bt))
-	      (index (make-instance 'sql-btree-index :primary bt 
-				    :key-form key-form
-				    :sc sc)))
+	      (index (build-btree-index sc :primary bt :key-form key-form)))
 	  (setf (gethash index-name (indices-cache bt)) index)
 	  (setf (gethash index-name indices) index)
 	  (setf (indices bt) indices)
@@ -190,6 +181,7 @@
     (with-transaction (:store-controller sc)
       (maphash 
        #'(lambda (k index) 
+	   (declare (ignore k))
 	   (multiple-value-bind (index? secondary-key)
 	       (funcall (key-fn index) index key value)
 	     (when index?
@@ -216,6 +208,7 @@
 	  (let ((indices (indices-cache bt)))
 	    (maphash 
 	     #'(lambda (k index) 
+		 (declare (ignore k))
 		 (multiple-value-bind (index? secondary-key)
 		     (funcall (key-fn index) index key value)
 		   (when index?
@@ -237,7 +230,6 @@
 	value))))
 
 
-
 (defclass sql-btree-index (btree-index sql-btree)
   ()
   (:metaclass persistent-metaclass)
@@ -290,8 +282,9 @@
   ;; apparently in postgres this is failing pretty awfully because 
   ;; sequence-exists-p return nil and then we get an error that the sequence exists!
   ;;    (unless (sequence-exists-p [persistent_seq])
-  (clsql::create-sequence [persistent_seq]
-		   :database con)
+  (clsql::create-sequence [persistent_seq] :database con)
+  ;; Leave room for root and class-root
+  (clsql::set-sequence-position [persistent_seq] 2 :database con)
   ;;)
   ;;    (unless (index-exists-p [idx_clctn_id])
   (clsql::create-index [idx_clctn_id] :on [keyvalue]
@@ -311,16 +304,16 @@
   ;;)
   )
 
-
 (defmethod open-controller ((sc sql-store-controller)
 			    ;; At present these three have no meaning
 			    &key 
 			    (recover nil)
 			    (recover-fatal nil) 
 			    (thread t))
+  (declare (ignore recover recover-fatal thread))
   (the sql-store-controller
-    (let* ((dbtype (car (second (:dbcn-spc sc))))
-	   (con (clsql:connect (cdr (second (:dbcn-spc sc)))
+    (let* ((dbtype (car (second (controller-spec sc))))
+	   (con (clsql:connect (cdr (second (controller-spec sc)))
 ;; WARNING: This line of code forces us to use postgresql.
 ;; If this were parametrized upwards we could concievably try 
 ;; other backends.
@@ -328,7 +321,6 @@
 ;; DNK :postgresql
 ;;			      :database-type :postgresql
 			      :if-exists :old)))
-      (setf (gethash (:dbcn-spc sc) *dbconnection-spec*) sc)
       (setf (slot-value sc 'db) con)
       ;; Now we should make sure that the KEYVALUE table exists, and, if 
       ;; it does not, we need to create it..
@@ -336,32 +328,22 @@
       ;; can put it in a function....
       (unless (keyvalue-table-exists con)
 	(create-keyvalue-table con))
-      (setf (slot-value sc 'root) (build-btree sc))
-      (setf (slot-value sc 'class-root) (build-indexed-btree sc))
-      ;; Actaully, it would seem here that we must further set the oid
-      ;; of the root tree to 0 to ensure that we read the correct thing
-      ;; when we next opent he controller...
-      (setf (oid (slot-value sc 'root)) 0)
+      ;; These should get oid 0 and 1 respectively 
+      (setf (slot-value sc 'root) (make-instance 'sql-btree :sc sc :from-oid 0))
+      (setf (slot-value sc 'class-root) (make-instance 'sql-indexed-btree :sc sc :from-oid 1))
       sc)
     )
   )
 
-(defun make-sql-btree (sc)
-  (let ((bt (make-instance 'sql-btree :sc sc)))
-    (setf (:dbcn-spc-pst bt) (:dbcn-spc sc))
-    bt)
-  )
-
 (defmethod close-controller ((sc sql-store-controller))
   (when (slot-value sc 'db)
-    ;; close the conneciton
+    ;; close the connection
     ;; (actually clsql has pooling and other complications, I am not sure
     ;; that this is complete.)
     (clsql:disconnect :database (controller-db sc))
     (setf (slot-value sc 'root) nil)
     ))
 
-
 ;; Because this is part of the public
 ;; interface that I'm tied to, it has to accept a store-controller...
 (defmethod next-oid ((sc sql-store-controller ))
@@ -370,7 +352,6 @@
 		   :database con))
   )
 
-
 ;; if add-to-root is a method, then we can make it class dependent...
 ;; otherwise we have to change the original code.  There is 
 ;; almost no way to implement this without either changing the existing
@@ -379,15 +360,14 @@
 ;; a proper method myself, but I will give it a name so it doesn't 
 ;; conflict with 'add-to-root.  'add-to-root can remain a convenience symbol,
 ;; that will end up calling this routine!
-(defmethod sql-add-to-root (key value (pgsc sql-store-controller ) con)
+(defun sql-add-to-root (key value pgsc con)
   (sql-add-to-clcn 0 key value pgsc con)
   )
-;;(defmethod sql-add-to-root (key value dbcon)
-;;  (sql-add-to-clcn 0 key value sc dbcon)
-;;  )
 
-(defmethod sql-add-to-clcn ((clcn integer) key value sc con
+(defun sql-add-to-clcn (clcn key value sc con
 			    &key (insert-only nil))
+  (declare (ignore sc))
+  (assert (integerp clcn))
   (let (
 	(vbs 
 	 (serialize-to-base64-string value))
@@ -411,9 +391,9 @@
   )
 
 
-
-(defmethod sql-get-from-root (key sc con)
-  (sql-get-from-clcn 0 key sc con))
+(defun sql-get-from-root (key sc con)
+  (sql-get-from-clcn 0 key sc con)
+  )
 
 ;; This is a major difference betwen SQL and BDB:
 ;; BDB plans to give you one value and let you iterate, but
@@ -431,10 +411,13 @@
 ;; To do that I have to read in all of the values and deserialized them
 ;; This could be a good reason to keep the oids out, and separte, in 
 ;; a separate column.
-(defmethod sql-get-from-clcn ((clcn integer) key sc con)
+(defun sql-get-from-clcn (clcn key sc con)
+  (assert (integerp clcn))
   (sql-get-from-clcn-nth clcn key sc con 0)
   )
-(defmethod sql-get-from-clcn-nth ((clcn integer) key sc con (n integer))
+
+(defun sql-get-from-clcn-nth (clcn key sc con n)
+  (assert (and (integerp clcn) (integerp n)))
   (let* (
 	 (kbs 
 	  (serialize-to-base64-string key))
@@ -463,7 +446,8 @@
 		t)
 	(values nil nil))))
 
-(defmethod sql-get-from-clcn-cnt ((clcn integer) key con)
+(defun sql-get-from-clcn-cnt (clcn key con)
+  (assert (integerp clcn))
   (let* (
 	 (kbs (serialize-to-base64-string key))
 	 (tuples
@@ -474,7 +458,8 @@
 		  )))
     (caar tuples)))
 
-(defmethod sql-dump-clcn ((clcn integer) sc con)
+(defun sql-dump-clcn (clcn sc con)
+  (assert (integerp clcn))
   (let* (
 	 (tuples
 	  (clsql::select [key] [value]
@@ -485,11 +470,12 @@
     (mapcar #'(lambda (x) (mapcar #'(lambda (q) (deserialize-from-base64-string q :sc sc)) x))
 	    tuples)))
 
-(defmethod sql-from-root-existsp (key con)
+(defun sql-from-root-existsp (key con)
   (sql-from-clcn-existsp 0 key con)
   )
 
-(defmethod sql-from-clcn-existsp ((clcn integer) key con)
+(defun sql-from-clcn-existsp (clcn key con)
+  (assert (integerp clcn))
   (let* (
 	 (kbs (with-buffer-streams (out-buf)
 		(serialize-to-base64-string key))
@@ -505,11 +491,14 @@
 	nil)
     ))
 
-(defmethod sql-remove-from-root (key sc con)
+(defun sql-remove-from-root (key sc con)

[53 lines skipped]




More information about the Elephant-cvs mailing list