Truncate all tables in a single command, fix #61.

The truncate command is only sent to PostgreSQL when we didn't just
CREATE TABLE before. Some refactoring would be necessary to fit the
TRUNCATE command within the same transaction as the CREATE TABLE
command, for PostgreSQL performances.

This patch has been testing with MySQL and SQLite sources, the trick is
that to be able to test it, it's needed to first make a full
import (creating the target tables), so the test are not modified yet.
This commit is contained in:
Dimitri Fontaine 2014-05-19 18:07:35 +02:00
parent c3742a9410
commit e710cacad1
5 changed files with 57 additions and 36 deletions

View File

@ -70,7 +70,7 @@
#:with-pgsql-connection #:with-pgsql-connection
#:pgsql-execute #:pgsql-execute
#:pgsql-execute-with-timing #:pgsql-execute-with-timing
#:truncate-table #:truncate-tables
#:copy-from-file #:copy-from-file
#:copy-from-queue #:copy-from-queue
#:list-databases #:list-databases
@ -212,6 +212,7 @@
#:list-tables-and-fkeys #:list-tables-and-fkeys
#:list-table-oids #:list-table-oids
#:create-tables #:create-tables
#:truncate-tables
#:format-pgsql-column #:format-pgsql-column
#:format-extra-type #:format-extra-type
#:make-pgsql-fkey #:make-pgsql-fkey
@ -244,6 +245,7 @@
#:pgsql-execute-with-timing #:pgsql-execute-with-timing
#:apply-identifier-case #:apply-identifier-case
#:create-tables #:create-tables
#:truncate-tables
#:format-pgsql-column #:format-pgsql-column
#:make-pgsql-index #:make-pgsql-index
#:index-table-name #:index-table-name

View File

@ -110,11 +110,6 @@
;;; ;;;
;;; PostgreSQL Utility Queries ;;; PostgreSQL Utility Queries
;;; ;;;
(defun truncate-table (dbname table-name)
"Truncate given TABLE-NAME in database DBNAME"
(pomo:with-connection (get-connection-spec dbname)
(set-session-gucs *pg-settings*)
(pomo:execute (format nil "truncate ~a;" table-name))))
(defun list-databases (&optional (username "postgres")) (defun list-databases (&optional (username "postgres"))
"Connect to a local database and get the database list" "Connect to a local database and get the database list"

View File

@ -176,6 +176,18 @@
(pgsql-execute sql :client-min-messages client-min-messages) (pgsql-execute sql :client-min-messages client-min-messages)
finally (return nb-tables))) finally (return nb-tables)))
(defun truncate-tables (dbname table-name-list
&key identifier-case)
"Truncate given TABLE-NAME in database DBNAME"
(pomo:with-connection (get-connection-spec dbname)
(set-session-gucs *pg-settings*)
(let ((sql (format nil "TRUNCATE ~{~s~^,~};"
(loop :for table-name :in table-name-list
:collect (apply-identifier-case table-name
identifier-case)))))
(log-message :notice "~a" sql)
(pomo:execute sql))))
;;; ;;;
;;; Index support ;;; Index support

View File

@ -351,8 +351,8 @@
(lp:make-channel))))) (lp:make-channel)))))
;; if asked, first drop/create the tables on the PostgreSQL side ;; if asked, first drop/create the tables on the PostgreSQL side
(when (and (or create-tables schema-only) (not data-only))
(handler-case (handler-case
(cond ((and (or create-tables schema-only) (not data-only))
(prepare-pgsql-database all-columns (prepare-pgsql-database all-columns
all-indexes all-indexes
all-fkeys all-fkeys
@ -361,7 +361,12 @@
:state state-before :state state-before
:foreign-keys foreign-keys :foreign-keys foreign-keys
:identifier-case identifier-case :identifier-case identifier-case
:include-drop include-drop) :include-drop include-drop))
(t
(when truncate
(truncate-tables *pg-dbname*
(mapcar #'car all-columns)
:identifier-case identifier-case))))
;; ;;
;; In case some error happens in the preparatory transaction, we ;; In case some error happens in the preparatory transaction, we
;; need to stop now and refrain from trying to load the data into ;; need to stop now and refrain from trying to load the data into
@ -370,7 +375,7 @@
(cl-postgres:database-error (e) (cl-postgres:database-error (e)
(declare (ignore e)) ; a log has already been printed (declare (ignore e)) ; a log has already been printed
(log-message :fatal "Failed to create the schema, see above.") (log-message :fatal "Failed to create the schema, see above.")
(return-from copy-database)))) (return-from copy-database)))
(loop (loop
for (table-name . columns) in (append all-columns view-columns) for (table-name . columns) in (append all-columns view-columns)
@ -401,7 +406,7 @@
;; first COPY the data from MySQL to PostgreSQL, using copy-kernel ;; first COPY the data from MySQL to PostgreSQL, using copy-kernel
(unless schema-only (unless schema-only
(copy-from table-source :kernel copy-kernel :truncate truncate)) (copy-from table-source :kernel copy-kernel))
;; Create the indexes for that table in parallel with the next ;; Create the indexes for that table in parallel with the next
;; COPY, and all at once in concurrent threads to benefit from ;; COPY, and all at once in concurrent threads to benefit from

View File

@ -221,7 +221,8 @@
reset-sequences reset-sequences
only-tables only-tables
including including
excluding) excluding
(identifier-case :downcase))
"Stream the given SQLite database down to PostgreSQL." "Stream the given SQLite database down to PostgreSQL."
(let* ((summary (null *state*)) (let* ((summary (null *state*))
(*state* (or *state* (make-pgstate))) (*state* (or *state* (make-pgstate)))
@ -247,13 +248,19 @@
(pg-dbname (target-db sqlite))) (pg-dbname (target-db sqlite)))
;; if asked, first drop/create the tables on the PostgreSQL side ;; if asked, first drop/create the tables on the PostgreSQL side
(when (and (or create-tables schema-only) (not data-only)) (cond ((and (or create-tables schema-only) (not data-only))
(log-message :notice "~:[~;DROP then ~]CREATE TABLES" include-drop) (log-message :notice "~:[~;DROP then ~]CREATE TABLES" include-drop)
(with-stats-collection ("create, truncate" (with-stats-collection ("create, truncate"
:state state-before :state state-before
:summary summary) :summary summary)
(with-pgsql-transaction () (with-pgsql-transaction ()
(create-tables all-columns :include-drop include-drop)))) (create-tables all-columns
:include-drop include-drop
:identifier-case identifier-case))))
(truncate
(truncate-tables *pg-dbname* (mapcar #'car all-columns)
:identifier-case identifier-case)))
(loop (loop
for (table-name . columns) in all-columns for (table-name . columns) in all-columns
@ -268,7 +275,7 @@
:fields columns))) :fields columns)))
;; first COPY the data from SQLite to PostgreSQL, using copy-kernel ;; first COPY the data from SQLite to PostgreSQL, using copy-kernel
(unless schema-only (unless schema-only
(copy-from table-source :kernel copy-kernel :truncate truncate)) (copy-from table-source :kernel copy-kernel))
;; Create the indexes for that table in parallel with the next ;; Create the indexes for that table in parallel with the next
;; COPY, and all at once in concurrent threads to benefit from ;; COPY, and all at once in concurrent threads to benefit from