From 3c3aa36478f0609e60d83e6c936bf2096fcae726 Mon Sep 17 00:00:00 2001 From: Nathan Bird Date: Sun, 7 Mar 2010 15:17:51 -0500 Subject: [PATCH] First draft at making auto-increment more general. --- db-mysql/mysql-sql.lisp | 6 ++++++ sql/db-interface.lisp | 5 +++++ sql/generic-postgresql.lisp | 18 +++++++++++++++++- sql/oodml.lisp | 25 +++++++++++-------------- sql/package.lisp | 2 ++ 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/db-mysql/mysql-sql.lisp b/db-mysql/mysql-sql.lisp index eef9f42..80d9ce1 100644 --- a/db-mysql/mysql-sql.lisp +++ b/db-mysql/mysql-sql.lisp @@ -487,6 +487,12 @@ (%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) diff --git a/sql/db-interface.lisp b/sql/db-interface.lisp index 9c17b54..892a80e 100644 --- a/sql/db-interface.lisp +++ b/sql/db-interface.lisp @@ -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)) diff --git a/sql/generic-postgresql.lisp b/sql/generic-postgresql.lisp index 25f6708..67175de 100644 --- a/sql/generic-postgresql.lisp +++ b/sql/generic-postgresql.lisp @@ -218,7 +218,7 @@ (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) @@ -241,6 +241,20 @@ (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)) @@ -380,3 +394,5 @@ (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 diff --git a/sql/oodml.lisp b/sql/oodml.lisp index e2f98a3..e50905e 100644 --- a/sql/oodml.lisp +++ b/sql/oodml.lisp @@ -185,15 +185,6 @@ (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))) @@ -234,15 +225,21 @@ :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 diff --git a/sql/package.lisp b/sql/package.lisp index 9e9dcb6..3847827 100644 --- a/sql/package.lisp +++ b/sql/package.lisp @@ -1,3 +1,4 @@ + ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION @@ -129,6 +130,7 @@ #: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 -- 2.34.1