Implement support for update and delete rules for MysQL FKeys, fixes #141.

This commit is contained in:
Dimitri Fontaine 2015-01-14 18:35:48 +01:00
parent 47aa02d844
commit 9f45b9864a
2 changed files with 31 additions and 15 deletions

View File

@ -58,7 +58,7 @@
;;; API for Foreign Keys
;;;
(defstruct pgsql-fkey
name table-name columns foreign-table foreign-columns)
name table-name columns foreign-table foreign-columns update-rule delete-rule)
(defgeneric format-pgsql-create-fkey (fkey)
(:documentation
@ -79,12 +79,16 @@
(foreign-columns (mapcar #'apply-identifier-case
(pgsql-fkey-foreign-columns fk))))
(format nil
"ALTER TABLE ~a ADD CONSTRAINT ~a FOREIGN KEY(~{~a~^,~}) REFERENCES ~a(~{~a~^,~})"
"ALTER TABLE ~a ADD CONSTRAINT ~a FOREIGN KEY(~{~a~^,~}) REFERENCES ~a(~{~a~^,~})~:[~*~; ON UPDATE ~a~]~:[~*~; ON DELETE ~a~]"
table-name
constraint-name
fkey-columns
foreign-table
foreign-columns)))
foreign-columns
(pgsql-fkey-update-rule fk)
(pgsql-fkey-update-rule fk)
(pgsql-fkey-delete-rule fk)
(pgsql-fkey-delete-rule fk))))
(defmethod format-pgsql-drop-fkey ((fk pgsql-fkey) &key all-pgsql-fkeys)
"Generate the PostgreSQL statement to rebuild a MySQL Foreign Key"

View File

@ -268,28 +268,38 @@ GROUP BY table_name, index_name;"
"Get the list of MySQL Foreign Keys definitions per table."
(loop
with schema = nil
for (table-name name ftable cols fcols)
for (table-name name ftable cols fcols update-rule delete-rule)
in (mysql-query (format nil "
SELECT i.table_name, i.constraint_name, k.referenced_table_name ft,
SELECT tc.table_name, tc.constraint_name, k.referenced_table_name ft,
group_concat( k.column_name
order by k.ordinal_position) as cols,
group_concat( k.referenced_column_name
order by k.position_in_unique_constraint) as fcols
order by k.position_in_unique_constraint) as fcols,
rc.update_rule, rc.delete_rule
FROM information_schema.table_constraints tc
JOIN information_schema.referential_constraints rc
ON rc.constraint_schema = tc.table_schema
AND rc.constraint_name = tc.constraint_name
AND rc.table_name = tc.table_name
FROM information_schema.table_constraints i
LEFT JOIN information_schema.key_column_usage k
USING (table_schema, table_name, constraint_name)
ON k.table_schema = tc.table_schema
AND k.table_name = tc.table_name
AND k.constraint_name = tc.constraint_name
WHERE i.table_schema = '~a'
WHERE tc.table_schema = '~a'
AND k.referenced_table_schema = '~a'
AND i.constraint_type = 'FOREIGN KEY'
~:[~*~;and table_name in (~{'~a'~^,~})~]
~:[~*~;and (~{table_name ~a~^ or ~})~]
~:[~*~;and (~{table_name ~a~^ and ~})~]
AND tc.constraint_type = 'FOREIGN KEY'
~:[~*~;and tc.table_name in (~{'~a'~^,~})~]
~:[~*~;and (~{tc.table_name ~a~^ or ~})~]
~:[~*~;and (~{tc.table_name ~a~^ and ~})~]
GROUP BY table_name, constraint_name, ft;"
GROUP BY tc.table_name, tc.constraint_name, ft"
(db-name *connection*) (db-name *connection*)
only-tables ; do we print the clause?
only-tables
@ -303,7 +313,9 @@ GROUP BY table_name, index_name;"
:table-name table-name
:columns (sq:split-sequence #\, cols)
:foreign-table ftable
:foreign-columns (sq:split-sequence #\, fcols))))
:foreign-columns (sq:split-sequence #\, fcols)
:update-rule update-rule
:delete-rule delete-rule)))
(if entry
(push fk (cdr entry))
(push (cons table-name (list fk)) schema)))