diff --git a/pgloader.1 b/pgloader.1 index 0849508..d3182b4 100644 --- a/pgloader.1 +++ b/pgloader.1 @@ -2678,6 +2678,32 @@ EXCLUDING TABLE NAMES MATCHING \'LocalAccount\' in schema \'dbo\' . .IP "" 0 +. +.IP "\(bu" 4 +\fIALTER SCHEMA \'\.\.\.\' RENAME TO \'\.\.\.\'\fR +. +.IP +Allows to rename a schema on the flight, so that for instance the tables found in the schema \'dbo\' in your source database will get migrated into the schema \'public\' in the target database with this command: +. +.IP "" 4 +. +.nf + +ALTER SCHEMA \'dbo\' RENAME TO \'public\' +. +.fi +. +.IP "" 0 + +. +.IP "\(bu" 4 +\fIALTER TABLE NAMES MATCHING \.\.\. IN SCHEMA \'\.\.\.\'\fR +. +.IP +See the MySQL explanation for this clause above\. It works the same in the context of migrating from MS SQL, only with the added option to specify the name of the schema where to find the definition of the target tables\. +. +.IP +The matching is done in pgloader itself, with a Common Lisp regular expression lib, so doesn\'t depend on the \fILIKE\fR implementation of MS SQL, nor on the lack of support for regular expressions in the engine\. . .IP "" 0 . diff --git a/pgloader.1.md b/pgloader.1.md index 9dcfe05..86d044d 100644 --- a/pgloader.1.md +++ b/pgloader.1.md @@ -2195,6 +2195,25 @@ The `mssql` command accepts the following clauses and options: EXCLUDING TABLE NAMES MATCHING 'LocalAccount' in schema 'dbo' + - *ALTER SCHEMA '...' RENAME TO '...'* + + Allows to rename a schema on the flight, so that for instance the tables + found in the schema 'dbo' in your source database will get migrated into + the schema 'public' in the target database with this command: + + ALTER SCHEMA 'dbo' RENAME TO 'public' + + - *ALTER TABLE NAMES MATCHING ... IN SCHEMA '...'* + + See the MySQL explanation for this clause above. It works the same in + the context of migrating from MS SQL, only with the added option to + specify the name of the schema where to find the definition of the + target tables. + + The matching is done in pgloader itself, with a Common Lisp regular + expression lib, so doesn't depend on the *LIKE* implementation of MS + SQL, nor on the lack of support for regular expressions in the engine. + ### DEFAULT MS SQL CASTING RULES When migrating from MS SQL the following Casting Rules are provided: diff --git a/src/parsers/command-alter-table.lisp b/src/parsers/command-alter-table.lisp index c2f789f..9cea3b0 100644 --- a/src/parsers/command-alter-table.lisp +++ b/src/parsers/command-alter-table.lisp @@ -28,6 +28,9 @@ (bind (((_ _ _ _ match-rule-target-list) alter-table)) match-rule-target-list))) +(defrule in-schema (and kw-in kw-schema quoted-namestring) + (:function third)) + (defrule rename-to (and kw-rename kw-to quoted-namestring) (:lambda (stmt) (bind (((_ _ new-name) stmt)) @@ -41,13 +44,17 @@ (defrule alter-table-action (or rename-to set-schema)) -(defrule alter-table-command (and alter-table-names-matching alter-table-action) +(defrule alter-table-command (and alter-table-names-matching + (? in-schema) + alter-table-action) (:lambda (alter-table-command) - (destructuring-bind (match-rule-target-list action) alter-table-command + (destructuring-bind (match-rule-target-list schema action) + alter-table-command (loop :for match-rule-target :in match-rule-target-list :collect (pgloader.schema::make-match-rule :type (first match-rule-target) :target (second match-rule-target) + :schema schema :action (first action) :args (rest action)))))) diff --git a/src/parsers/command-mssql.lisp b/src/parsers/command-mssql.lisp index 90e511c..4a792fe 100644 --- a/src/parsers/command-mssql.lisp +++ b/src/parsers/command-mssql.lisp @@ -70,6 +70,7 @@ gucs casts alter-schema + alter-table before-load after-load including-like-in-schema @@ -136,7 +137,7 @@ (defun lisp-code-for-loading-from-mssql (ms-db-conn pg-db-conn &key gucs casts before after options - alter-schema + alter-schema alter-table including excluding) `(lambda () ;; now is the time to load the CFFI lib we need (freetds) @@ -159,6 +160,7 @@ :including ',including :excluding ',excluding :alter-schema ',alter-schema + :alter-table ',alter-table :set-table-oids t ,@(remove-batch-control-option options)) @@ -168,7 +170,7 @@ (:lambda (source) (bind (((ms-db-uri pg-db-uri &key - gucs casts before after alter-schema + gucs casts before after alter-schema alter-table including excluding options) source)) (cond (*dry-run* @@ -180,6 +182,7 @@ :before before :after after :alter-schema alter-schema + :alter-table alter-table :options options :including including :excluding excluding)))))) diff --git a/src/sources/mssql/mssql.lisp b/src/sources/mssql/mssql.lisp index 0c0bac1..e5ae068 100644 --- a/src/sources/mssql/mssql.lisp +++ b/src/sources/mssql/mssql.lisp @@ -32,7 +32,7 @@ (let* ((sql (format nil "SELECT ~{~a~^, ~} FROM [~a].[~a];" (get-column-list (fields mssql)) (schema-source-name (table-schema (source mssql))) - (table-name (source mssql))))) + (table-source-name (source mssql))))) (log-message :debug "~a" sql) (handler-case (handler-bind diff --git a/src/utils/alter-table.lisp b/src/utils/alter-table.lisp index 0ccf9e4..5ebebd8 100644 --- a/src/utils/alter-table.lisp +++ b/src/utils/alter-table.lisp @@ -12,7 +12,7 @@ :action #'pgloader.schema::alter-table-set-schema :args (list "mv")) |# -(defstruct match-rule type target action args) +(defstruct match-rule type target schema action args) (defgeneric alter-table (object alter-table-rule-list)) @@ -67,10 +67,14 @@ (defmethod rule-matches ((match-rule match-rule) (table table)) "Return non-nil when TABLE matches given MATCH-RULE." - (let ((table-name (table-source-name table))) - (ecase (match-rule-type match-rule) - (:string (string= (match-rule-target match-rule) table-name)) - (:regex (cl-ppcre:scan (match-rule-target match-rule) table-name))))) + (let ((schema-name (schema-source-name (table-schema table))) + (rule-schema (match-rule-schema match-rule)) + (table-name (table-source-name table))) + (when (or (null rule-schema) + (and rule-schema (string= rule-schema schema-name))) + (ecase (match-rule-type match-rule) + (:string (string= (match-rule-target match-rule) table-name)) + (:regex (cl-ppcre:scan (match-rule-target match-rule) table-name)))))) (defmethod rule-matches ((match-rule match-rule) (schema schema)) "Return non-nil when TABLE matches given MATCH-RULE."