Update of /project/elephant/cvsroot/elephant/src/db-clsql In directory clnet:/tmp/cvs-serv26423/src/db-clsql
Modified Files: sql-collections.lisp sql-controller.lisp Log Message: More robust upgrade mechanism, one bug fix, better user of PK
--- /project/elephant/cvsroot/elephant/src/db-clsql/sql-collections.lisp 2007/02/02 23:51:58 1.9 +++ /project/elephant/cvsroot/elephant/src/db-clsql/sql-collections.lisp 2007/02/08 22:33:35 1.10 @@ -526,7 +526,7 @@ (let ((cur-pk (get-current-key cursor))) (decf (:sql-crsr-ck cursor)) (if (equal cur-pk (get-current-key cursor)) - (decf (:dp-nmbr cursor)) + (setf (:dp-nmbr cursor) (max 0 (- (:dp-nmbr cursor) 1))) (setf (:dp-nmbr cursor) (sql-get-from-clcn-cnt (cursor-oid cursor) (get-current-key cursor) @@ -593,12 +593,13 @@ (setf (:sql-crsr-ck cursor) (- (length (:sql-crsr-ks cursor)) 1)) (setf (:dp-nmbr cursor) + (max 0 (- (sql-get-from-clcn-cnt (cursor-oid cursor) (get-current-key cursor) (get-con (cursor-btree cursor)) ) - 1)) + 1))) (assert (>= (:dp-nmbr cursor) 0)) (setf (cursor-initialized-p cursor) t) (has-key-value-scnd cursor :returnpk returnpk) @@ -615,10 +616,11 @@ (progn (setf (:sql-crsr-ck cursor) (- (:sql-crsr-ck cursor) (+ 1 (:dp-nmbr cursor)))) (setf (:dp-nmbr cursor) + (max 0 (- (sql-get-from-clcn-cnt (cursor-oid cursor) (get-current-key cursor) (get-con (cursor-btree cursor)) -) 1)) + ) 1))) (has-key-value-scnd cursor :returnpk returnpk)) (cursor-last-x cursor :returnpk returnpk)))
--- /project/elephant/cvsroot/elephant/src/db-clsql/sql-controller.lisp 2007/02/07 22:54:12 1.17 +++ /project/elephant/cvsroot/elephant/src/db-clsql/sql-controller.lisp 2007/02/08 22:33:35 1.18 @@ -34,13 +34,13 @@ ( ;; (db :accessor controller-db :initarg :db :initform nil) (dbcons :accessor controller-db-table :initarg :db :initform nil) + (uses-pk :accessor uses-pk-of :initarg :uses-pk) ) (: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."))
- ;; This should be much more elegant --- but as of Feb. 6, SBCL 1.0.2 has a weird, ;; unpleasant bug when ASDF tries to load this stuff. ;; (defvar *thread-table-lock* nil) @@ -300,6 +300,20 @@ (clsql:table-exists-p [keyvalue] :database con :owner :all) )
+;; Our goal here is to see if the "pk" column exists.... +;; if it does, we can use a certain optimization the sql-get-from-clcn-nth. +;; Post 6.1 versions should have it, but 6.0 versions won't. +;; My goal here is to be as robust as possible; there is no portable way +;; to add a column nicely. If you want to upgrade (which will really only +;; help if you use duplicate keys), then do a migration from your old repository +;; to a new repository. +(defun query-uses-pk (con) + ;; we want to use ":owner :all" because we don't really care who created + ;; the table, as long as we have the rights we need! + (member "pk" (clsql:list-attributes [keyvalue] :database con :owner :all) + :test 'equal) + ) +
;; This is just an initial version; it is possible that ;; we might someday wish to use blobs instead; certainly, I am @@ -320,6 +334,8 @@ ;; CREATE-SEQUENCE and SEQUENCE-NEXT. That would solve our problem!
;; ALL OF THIS needs to be inside a transaction. + +;; At one time this was conditional, but all NEW repositories should have this. (clsql::create-sequence [serial] :database con) (clsql::query (format nil "create table keyvalue ( @@ -329,19 +345,17 @@ value varchar )") :database con) +;; (clsql::create-table [keyvalue] +;; ;; This is most likely to work with any database system.. +;; '( +;; ([clctn_id] integer :not-null) +;; ([key] text :not-null) +;; ([value] text) +;; ) +;; :database con)
- ;; (clsql::create-table [keyvalue] - - ;; ;; This is most likely to work with any database system.. - ;; '( - ;; ([clctn_id] integer :not-null) - ;; ([key] text :not-null) - ;; ([value] text) - ;; ) - ;; :database con) - - ;; :constraints '("PRIMARY KEY (clctn_id key)" - ;; "UNIQUE (clctn_id,key)") +;; :constraints '("PRIMARY KEY (clctn_id key)" +;; "UNIQUE (clctn_id,key)")
;; apparently in postgres this is failing pretty awfully because ;; sequence-exists-p return nil and then we get an error that the sequence exists! @@ -412,8 +426,9 @@ ;; Now we should make sure that the KEYVALUE table exists, and, if ;; it does not, we need to create it.. (unless (keyvalue-table-exists con) - (with-transaction (:store-controller sc) - (create-keyvalue-table con))) + (with-transaction (:store-controller sc) + (create-keyvalue-table con))) + (setf (uses-pk-of sc) (query-uses-pk con)) (unless (version-table-exists con) (with-transaction (:store-controller sc) (create-version-table con))) @@ -450,8 +465,6 @@
(defmethod reconnect-controller ((sc sql-store-controller)) (clsql:reconnect :database (controller-db sc) :force nil) -;; (setf (controller-db sc) -;; (clsql:reconnect :database (controller-db sc))) )
(defmethod close-controller ((sc sql-store-controller)) @@ -543,17 +556,21 @@ (let* ((con (controller-db sc)) (kbs (serialize-to-base64-string key sc)) - (offsetquery (format nil "select value from keyvalue where clctn_id = ~A and key = '~A' order by pk offset ~A limit 1 " - clcn - kbs - n)) + (offsetquery (if (uses-pk-of sc) + (format nil "select value from keyvalue where clctn_id = ~A and key = '~A' order by pk offset ~A limit 1 " + clcn + kbs + n) + nil)) (tuples - (clsql::query offsetquery :database con) -;; (clsql::select [value] -;; :from [keyvalue] -;; :where [and [= [clctn_id] clcn] [= [key] kbs]] -;; :database con -;; ) + (if (uses-pk-of sc) + (clsql::query offsetquery :database con) + (clsql::select [value] + :from [keyvalue] + :where [and [= [clctn_id] clcn] [= [key] kbs]] + :database con + ) + ) ) ) ;; Get the lowest value by sorting and taking the first value; @@ -565,21 +582,22 @@ ;; that efficiently without changing the database structure; ;; but that's OK, I could add a column to support that ;; relatively easily later on. - (if tuples - (values (deserialize-from-base64-string (caar tuples) sc) - t) - (values nil nil)) - -;; (if (< n (length tuples)) -;; (values (nth n (sort -;; (mapcar -;; #'(lambda (x) -;; (deserialize-from-base64-string (car x) sc)) -;; tuples) -;; #'my-generic-less-than)) -;; t) -;; (values nil nil)) -)) + (if (uses-pk-of sc) + (if tuples + (values (deserialize-from-base64-string (caar tuples) sc) + t) + (values nil nil)) + (if (< n (length tuples)) + (values (nth n (sort + (mapcar + #'(lambda (x) + (deserialize-from-base64-string (car x) sc)) + tuples) + #'my-generic-less-than)) + t) + (values nil nil)) + ) + ))
(defun sql-get-from-clcn-cnt (clcn key sc) (assert (integerp clcn)) @@ -597,11 +615,20 @@ (assert (integerp clcn)) (let* ((con (controller-db sc)) (tuples - (clsql::select [pk] [key] [value] + (if (uses-pk-of sc) + (clsql::select [pk] [key] [value] :from [keyvalue] :where [and [= [clctn_id] clcn]] :database con - ))) + ) + (clsql::select [key] [value] + :from [keyvalue] + :where [and [= [clctn_id] clcn]] + :database con + ) + ) + ) + ) (mapcar #'(lambda (x) (mapcar #'(lambda (q) (deserialize-from-base64-string q :sc sc)) x)) tuples)))
@@ -678,24 +705,11 @@ (if (or (null to-remove) (my-generic-less-than (car tuple) to-remove)) (setf to-remove (car tuple)))) - ;; (nth 0 (sort - ;; (mapcar - ;; #'(lambda (x) - ;; (deserialize-from-base64-string (car x) :sc sc)) - ;; tuples) - ;; #'my-generic-less-than))))) - ;; (format t "to-remove = ~A~%" to-remove) (clsql::delete-records :from [keyvalue] :where [and [= [clctn_id] clcn] [= [key] kbs] [= [value] to-remove]] :database con ) - ;; (format t "After deletion = ~A~%" - ;; (clsql::select [value] - ;; :from [keyvalue] - ;; :where [and [= [clctn_id] clcn] [= [key] kbs]] - ;; :database con - ;; )) ) ) )