Implement and use DROP ... IF EXISTS.

In cases where we have a WITH include drop option, we are generating
lots of SQL DROP statements. We may be running an empty target database
or in other situations where the target object of the DROP command might
not exists. Add support for that case.
This commit is contained in:
Dimitri Fontaine 2016-09-10 18:01:04 +02:00
parent 5ad21bdbfb
commit 5b6adb02b0
3 changed files with 32 additions and 25 deletions

View File

@ -26,7 +26,7 @@
(loop :for sqltype :in sqltype-list
:when include-drop
:count t
:do (pgsql-execute (format-drop-sql sqltype :cascade t)
:do (pgsql-execute (format-drop-sql sqltype :cascade t :if-exists t)
:client-min-messages client-min-messages)
:do (pgsql-execute
(format-create-sql sqltype :if-not-exists if-not-exists)
@ -38,8 +38,9 @@
include-drop)
"Return the list of CREATE TABLE statements to run against PostgreSQL."
(loop :for table :in table-list
:when include-drop
:collect (format-drop-sql table :cascade t)
:collect (format-drop-sql table :cascade t :if-exists t)
:collect (format-create-sql table :if-not-exists if-not-exists)))
@ -169,13 +170,13 @@
"Drop all Foreign Key Definitions given, to prepare for a clean run."
(loop :for table :in (table-list catalog)
:sum (loop :for fkey :in (table-fkey-list table)
:for sql := (format-drop-sql fkey :cascade cascade)
:for sql := (format-drop-sql fkey :cascade cascade :if-exists t)
:do (pgsql-execute sql)
:count t)
;; also DROP the foreign keys that depend on the indexes we want to DROP
:sum (loop :for index :in (table-index-list table)
:sum (loop :for fkey :in (index-fk-deps index)
:for sql := (format-drop-sql fkey :cascade t)
:for sql := (format-drop-sql fkey :cascade t :if-exists t)
:do (progn
(log-message :debug "EXTRA FK DEPS!")
(pgsql-execute sql))
@ -257,7 +258,7 @@
(table (table-index-list table-or-catalog))
(catalog (loop :for table :in (table-list table-or-catalog)
:append (table-index-list table))))
:collect (format-drop-sql index :cascade cascade))))
:collect (format-drop-sql index :cascade cascade :if-exists t))))
(pgsql-execute sql-index-list)
;; return how many indexes we just DROPed
(length sql-index-list)))
@ -265,7 +266,7 @@
;;;
;;; Higher level API to care about indexes
;;;
(defun maybe-drop-indexes (catalog &key (section :pre) drop-indexes)
(defun maybe-drop-indexes (catalog &key drop-indexes)
"Drop the indexes for TABLE-NAME on TARGET PostgreSQL connection, and
returns a list of indexes to create again. A PostgreSQL connection must
already be active when calling that function."

View File

@ -12,8 +12,9 @@
if-not-exists
(schema-name schema)))
(defmethod format-drop-sql ((schema schema) &key (stream nil) cascade)
(format stream "DROP SCHEMA ~s~@[ CASCADE~];" (schema-name schema) cascade))
(defmethod format-drop-sql ((schema schema) &key (stream nil) cascade if-exists)
(format stream "DROP SCHEMA~@[ IF EXISTS~] ~s~@[ CASCADE~];"
if-exists (schema-name schema) cascade))
;;;
@ -27,8 +28,9 @@
(sqltype-name sqltype)
(sqltype-extra sqltype)))))
(defmethod format-drop-sql ((sqltype sqltype) &key (stream nil) cascade)
(format stream "DROP TYPE ~s~@[ CASCADE~];" (sqltype-name sqltype) cascade))
(defmethod format-drop-sql ((sqltype sqltype) &key (stream nil) cascade if-exists)
(format stream "DROP TYPE~:[~; IF EXISTS~] ~s~@[ CASCADE~];"
if-exists (sqltype-name sqltype) cascade))
;;;
@ -59,11 +61,11 @@
(format s "~:[~;,~]~%" last?))))
(format s ");~%"))))
(defmethod format-drop-sql ((table table) &key (stream nil) cascade)
(defmethod format-drop-sql ((table table) &key (stream nil) cascade (if-exists t))
"Return the PostgreSQL DROP TABLE IF EXISTS statement for TABLE-NAME."
(format stream
"DROP TABLE IF EXISTS ~a~@[ CASCADE~];"
(format-table-name table) cascade))
"DROP TABLE~:[~; IF EXISTS~] ~a~@[ CASCADE~];"
if-exists (format-table-name table) cascade))
;;;
@ -184,21 +186,23 @@
(index-columns index)
(index-filter index)))))))
(defmethod format-drop-sql ((index index) &key (stream nil) cascade)
(defmethod format-drop-sql ((index index) &key (stream nil) cascade if-exists)
(let* ((schema-name (schema-name (index-schema index)))
(index-name (index-name index)))
(cond ((index-conname index)
;; here always quote the constraint name, currently the name
;; comes from one source only, the PostgreSQL database catalogs,
;; so don't question it, quote it.
(format stream "ALTER TABLE ~a DROP CONSTRAINT ~s~@[ CASCADE~];"
(format stream
"ALTER TABLE ~a DROP CONSTRAINT~:[~; IF EXISTS~] ~s~@[ CASCADE~];"
(format-table-name (index-table index))
if-exists
(index-conname index)
cascade))
(t
(format stream "DROP INDEX ~@[~a.~]~a~@[ CASCADE~];"
schema-name index-name cascade)))))
(format stream "DROP INDEX~:[~; IF EXISTS~] ~@[~a.~]~a~@[ CASCADE~];"
if-exists schema-name index-name cascade)))))
;;;
@ -223,11 +227,11 @@
(fkey-delete-rule fk)
(fkey-delete-rule fk))))
(defmethod format-drop-sql ((fk fkey) &key (stream nil) cascade)
(defmethod format-drop-sql ((fk fkey) &key (stream nil) cascade if-exists)
(let* ((constraint-name (fkey-name fk))
(table-name (format-table-name (fkey-table fk))))
(format stream "ALTER TABLE ~a DROP CONSTRAINT ~s~@[ CASCADE~];"
table-name constraint-name cascade)))
(format stream "ALTER TABLE ~a DROP CONSTRAINT~:[~; IF EXISTS~] ~s~@[ CASCADE~];"
table-name if-exists constraint-name cascade)))
;;;
@ -242,9 +246,10 @@
(format-table-name (trigger-table trigger))
(trigger-procedure-name trigger)))
(defmethod format-drop-sql ((trigger trigger) &key (stream nil) cascade)
(defmethod format-drop-sql ((trigger trigger) &key (stream nil) cascade if-exists)
(format stream
"DROP TRIGGER ~a ON ~a~@[ CASCADE~];"
"DROP TRIGGER~:[~; IF EXISTS~] ~a ON ~a~@[ CASCADE~];"
if-exists
(trigger-name trigger)
(format-table-name (trigger-table trigger))
cascade))
@ -262,9 +267,10 @@
(procedure-language procedure)
(procedure-body procedure)))
(defmethod format-drop-sql ((procedure procedure) &key (stream nil) cascade)
(defmethod format-drop-sql ((procedure procedure) &key (stream nil) cascade if-exists)
(format stream
"DROP FUNCTION ~a()~@[ CASCADE~];" (procedure-name procedure) cascade))
"DROP FUNCTION~:[~; IF EXISTS~] ~a()~@[ CASCADE~];"
if-exists (procedure-name procedure) cascade))
;;;

View File

@ -27,7 +27,7 @@
(:documentation "Generate proper SQL command to create OBJECT in
PostgreSQL. The output is written to STREAM."))
(defgeneric format-drop-sql (object &key stream cascade)
(defgeneric format-drop-sql (object &key stream cascade if-exists)
(:documentation "Generate proper SQL command to drop OBJECT in PostgreSQL.
The output is written to STREAM."))