First draft at making auto-increment more general.
authorNathan Bird <nathan@acceleration.net>
Sun, 7 Mar 2010 20:17:51 +0000 (15:17 -0500)
committerNathan Bird <nathan@acceleration.net>
Sun, 7 Mar 2010 20:17:51 +0000 (15:17 -0500)
db-mysql/mysql-sql.lisp
sql/db-interface.lisp
sql/generic-postgresql.lisp
sql/oodml.lisp
sql/package.lisp

index eef9f42283db629062d267572eed5970a7950c18..80d9ce13e8e31b20444b803748ffa3de28debe56 100644 (file)
                         (%sequence-name-to-table sequence-name))
            database :auto nil))))
 
+(defmethod database-last-auto-increment-id ((database mysql-database) table column)
+  (declare (ignore table column))
+  (car (query "SELECT LAST_INSERT_ID();"
+             :flatp t :field-names nil
+             :database database)))
+
 (defmethod database-create (connection-spec (type (eql :mysql)))
   (destructuring-bind (host name user password) connection-spec
     (let ((database (database-connect (list host "" user password)
index 9c17b544dd0268993a6022e13b3677fadb107959..892a80e35b3cd5e96d825d2b1c96f05f2938ca77 100644 (file)
@@ -167,6 +167,11 @@ if unable to destory."))
 (defgeneric database-sequence-last (name database)
   (:documentation "Select the last value in sequence NAME in DATABASE."))
 
+(defgeneric database-last-autoincrement-id (database table column)
+  (:documentation "Many databases have the notion of an auto-increment
+  id; i.e. a sequence implicitly on a table. This function should
+  return that ID." ))
+
 (defgeneric database-start-transaction (database)
   (:documentation "Start a transaction in DATABASE.")
   (:method ((database t))
index 25f67082b6e123974477922f16cd3c3784c81120..67175de0373272ad118d03599c9fde50200d3fc4 100644 (file)
 (defmethod database-set-sequence-position (name (position integer)
                                                 (database generic-postgresql-database))
   (values
-   (parse-integer
+    (parse-integer
     (caar
      (database-query
       (format nil "SELECT SETVAL ('~A', ~A)" name position)
       (concatenate 'string "SELECT LAST_VALUE FROM " sequence-name)
       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)))
+    (first (clsql:query (format nil "SELECT currval ('~a')" seq-name)
+                :flatp t
+                :database database
+                :result-types '(integer)))))
+
 (defun postgresql-database-list (connection-spec type)
   (destructuring-bind (host name &rest other-args) connection-spec
     (declare (ignore name))
 (defmethod db-type-has-prepared-stmt? ((db-type (eql :postgresql-socket)))
   t)
 
+(defmethod db-type-has-auto-increment? ((db-type (eql :postgresql)))
+  t)
\ No newline at end of file
index e2f98a342b788044b54594acb5178cf65f9a70f8..e50905e93436755f53f37bbc49ce9f3bcc06412e 100644 (file)
             (list (sql-expression :attribute (view-class-slot-column slot))
                   (db-value-from-slot slot value database))))
 
-        (get-pk (pk-slot)
-          (if (member :auto-increment (listify (view-class-slot-db-constraints pk-slot)))
-              (setf (slot-value obj (slot-definition-name pk-slot))
-                    ;;this should probably be moved into it's own function.
-                    (car (query "SELECT LAST_INSERT_ID();"
-                                :flatp t :field-names nil
-                                :database database)))
-              (slot-value obj (slot-definition-name pk-slot))))
-
         (save-slots-for-class (view-class stored-slot-defs)
           (let ((pk-slot (car (keyslots-for-class view-class)))
                 (table (sql-expression :table (view-table view-class)))
                                          :this-class view-class)
                                  :database database)
                  (when (and pk-slot (not pk))
-                   (setf pk (slot-value obj (slot-definition-name pk-slot)))))
+                   (setf pk (slot-value obj (slot-definition-name pk-slot))))
+                 pk)
                 (t
                  (insert-records :into table
                                  :av-pairs av-pairs
                                  :database database)
-                 (when pk-slot
-                   (setf pk (or pk (get-pk pk-slot)))
-
-                   )))))))
+                 (when (and pk-slot (not pk))
+                   (setf pk (if (member :auto-increment (listify (view-class-slot-db-constraints pk-slot)))
+                                (setf (slot-value obj (slot-definition-name pk-slot))
+                                      (database-last-autoincrement-id database
+                                                                      table
+                                                                      pk-slot))))
+
+                   )
+                 pk))))))
 
 
       (save-slots-for-class
index 9e9dcb6b76f3bc110b516429424ed2d8d2318af9..3847827ccbdb2f5e44e9cda622ab3afc48ba2c25 100644 (file)
@@ -1,3 +1,4 @@
+
 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
 ;;;; *************************************************************************
 ;;;; FILE IDENTIFICATION
      #:database-list-sequences
      #:database-sequence-last
      #:database-sequence-exists-p
+     #:database-last-auto-increment-id
      #:database-list-attributes
      #:database-attribute-type
      #:database-type-library-loaded