Support :autoincrement for Postgres on table creation by rebuilding what Postgres...
authorHolger Schauer <Holger.Schauer@gmx.de>
Thu, 3 Mar 2011 14:48:26 +0000 (15:48 +0100)
committerKevin M. Rosenberg <kevin@rosenberg.net>
Wed, 30 Mar 2011 00:27:13 +0000 (18:27 -0600)
sql/generic-postgresql.lisp
sql/generics.lisp
sql/metaclasses.lisp
sql/ooddl.lisp
sql/oodml.lisp

index 67175de0373272ad118d03599c9fde50200d3fc4..9c72946a1d7e2444e849318e2a11a31c00a01da6 100644 (file)
       database nil nil)))))
 
 (defmethod database-last-auto-increment-id ((database generic-postgresql-database) table column)
-  (typecase table
-    (sql-ident (setf table (slot-value table 'name)))
-    (standard-db-class (setf table (view-table table))))
-  (typecase column
-    (sql-ident (setf column (slot-value column 'name)))
-    (view-class-slot-definition-mixin
-       (setf column (view-class-slot-column column))))
-  (let ((seq-name (format nil "~a_~a_seq" table column)))
+  (let (column-helper seq-name)
+    (typecase table
+      (sql-ident (setf table (slot-value table 'name)))
+      (standard-db-class (setf table (view-table table))))
+    (typecase column
+      (sql-ident (setf column-helper (slot-value column 'name)))
+      (view-class-slot-definition-mixin
+       (setf column-helper (view-class-slot-column column))))
+    (setq seq-name (or (view-class-slot-autoincrement-sequence column)
+                      (convert-to-db-default-case (format nil "~a_~a_seq" table column-helper) database)))
     (first (clsql:query (format nil "SELECT currval ('~a')" seq-name)
-                :flatp t
-                :database database
-                :result-types '(integer)))))
+                       :flatp t
+                       :database database
+                       :result-types '(:int)))))
+
+(defmethod database-generate-column-definition (class slotdef (database generic-postgresql-database))
+  ; handle autoincr slots special
+  (when (or (and (listp (view-class-slot-db-constraints slotdef))
+                (member :auto-increment (view-class-slot-db-constraints slotdef)))
+           (eql :auto-increment (view-class-slot-db-constraints slotdef))
+           (slot-value slotdef 'autoincrement-sequence))
+    (let ((sequence-name (database-make-autoincrement-sequence class slotdef database)))
+      (setf (view-class-slot-autoincrement-sequence slotdef) sequence-name)
+      (cond ((listp (view-class-slot-db-constraints slotdef))
+            (setf (view-class-slot-db-constraints slotdef)
+                  (remove :auto-increment 
+                          (view-class-slot-db-constraints slotdef)))
+            (unless (member :default (view-class-slot-db-constraints slotdef))
+              (setf (view-class-slot-db-constraints slotdef)
+                    (append
+                     (list :default (format nil "nextval('~a')" sequence-name))
+                     (view-class-slot-db-constraints slotdef)))))
+           (t
+            (setf (view-class-slot-db-constraints slotdef)
+                  (list :default (format nil "nextval('~a')" sequence-name)))))))
+  (call-next-method class slotdef database))
+
+(defmethod database-make-autoincrement-sequence (table column (database generic-postgresql-database))
+  (let* ((table-name (view-table table))
+        (column-name (view-class-slot-column column))
+        (sequence-name (or (slot-value column 'autoincrement-sequence)
+                           (convert-to-db-default-case 
+                            (format nil "~a_~a_SEQ" table-name column-name) database))))
+    (unless (sequence-exists-p sequence-name  :database database)
+      (database-create-sequence sequence-name database))
+    sequence-name))
 
 (defun postgresql-database-list (connection-spec type)
   (destructuring-bind (host name &rest other-args) connection-spec
index decc005de33aaba69ae897ebf9046de5a1625f1d..2208b8d10cc93bdca90716fddbd1ea4092460a60 100644 (file)
@@ -139,7 +139,8 @@ DATABASE-NULL-VALUE on the type of the slot."))
   )
 (defgeneric read-sql-value  (val type database db-type)
   )
-
+(defgeneric database-make-autoincrement-sequence (class slotdef database)
+  )
 
 ;; Generation of SQL strings from lisp expressions
 
index 530c674c55f6f7da589180bc618d731b0aa283bb..1ae635a9eb9ea3679192c83ed51cddebc07b0999 100644 (file)
@@ -314,7 +314,13 @@ column definition in the database.")
     :accessor specified-type
     :initarg specified-type
     :initform nil
-    :documentation "Internal slot storing the :type specified by user.")))
+    :documentation "Internal slot storing the :type specified by user.")
+   (autoincrement-sequence
+    :accessor view-class-slot-autoincrement-sequence
+    :initarg :autoincrement-sequence
+    :initform nil
+    :documentation "A string naming the (possibly automatically generated) sequence 
+for a slot with an :auto-increment constraint.")))
 
 (defparameter *db-info-lambda-list*
   '(&key join-class
index 33dca0408a0a3d9e7de51bc10324247098335d05..02c11f021df00c7d3bf1502c612ff4c4994696cc 100644 (file)
@@ -106,7 +106,7 @@ in DATABASE which defaults to *DEFAULT-DATABASE*."
                            (ordered-class-direct-slots self)
                            (ordered-class-slots self))))
     (dolist (slotdef ordered-slots)
-      (let ((res (database-generate-column-definition (class-name self)
+      (let ((res (database-generate-column-definition self
                                                       slotdef database)))
         (when res
           (push res schemadef))))
index 0ddaabad5d5444eda23851945f018cf7d9a3bd67..d47bbba447ec98914db2b883377c9c941debfdd9 100644 (file)
                                  :av-pairs av-pairs
                                  :database database)
                  (when (and pk-slot (not pk))
-                   (setf pk (if (member :auto-increment (listify (view-class-slot-db-constraints pk-slot)))
+                   (setf pk (if (or (member :auto-increment (listify (view-class-slot-db-constraints pk-slot)))
+                                    (not (null (view-class-slot-autoincrement-sequence pk-slot))))
                                 (setf (slot-value obj (slot-definition-name pk-slot))
                                       (database-last-auto-increment-id database
                                                                       table