Skip to content

Commit c019c16

Browse files
committed
Implement MATERIALIZE VIEWS support for MS SQL, and distribute.
The latter is not tested yet, but should have no impact if not used. Given how rare it is that I get a chance to play around with a MS SQL instance anyway, it might be better to push blind changes for it when it doesn't impact existing features…
1 parent bda06f8 commit c019c16

File tree

4 files changed

+100
-17
lines changed

4 files changed

+100
-17
lines changed

src/parsers/command-mssql.lisp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@
8383
casts
8484
alter-schema
8585
alter-table
86+
materialize-views
87+
distribute-commands
8688
before-load
8789
after-load
8890
including-like-in-schema
@@ -139,7 +141,8 @@
139141
(defun lisp-code-for-loading-from-mssql (ms-db-conn pg-db-conn
140142
&key
141143
gucs mssql-gucs
142-
casts before after options
144+
casts before after
145+
options distribute views
143146
alter-schema alter-table
144147
including excluding
145148
&allow-other-keys)
@@ -167,6 +170,8 @@
167170
:excluding ',excluding
168171
:alter-schema ',alter-schema
169172
:alter-table ',alter-table
173+
:materialize-views ',views
174+
:distribute ',distribute
170175
:set-table-oids t
171176
:on-error-stop on-error-stop
172177
,@(remove-batch-control-option options))
@@ -177,8 +182,8 @@
177182
(:lambda (source)
178183
(bind (((ms-db-uri pg-db-uri
179184
&key
180-
gucs mssql-gucs casts before after
181-
alter-schema alter-table
185+
gucs mssql-gucs casts views before after
186+
alter-schema alter-table distribute
182187
including excluding options)
183188
source))
184189
(cond (*dry-run*
@@ -188,10 +193,12 @@
188193
:gucs gucs
189194
:mssql-gucs mssql-gucs
190195
:casts casts
196+
:views views
191197
:before before
192198
:after after
193199
:alter-schema alter-schema
194200
:alter-table alter-table
201+
:distribute distribute
195202
:options options
196203
:including including
197204
:excluding excluding))))))

src/sources/mssql/mssql-cast-rules.lisp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@
8888
datetime-precision
8989
character-set-name collation-name)
9090

91+
(defmethod field-name ((field mssql-column) &key)
92+
(mssql-column-name field))
93+
9194
(defmethod mssql-column-ctype ((col mssql-column))
9295
"Build the ctype definition from the full mssql-column information."
9396
(let ((type (mssql-column-type col)))

src/sources/mssql/mssql-schema.lisp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,43 @@
213213
(loop :for col :in columns
214214
:collect (with-slots (name type) col
215215
(get-column-sql-expression name type))))
216+
217+
218+
219+
;;;
220+
;;; Materialize Views support
221+
;;;
222+
(defun create-ms-views (views-alist)
223+
"VIEWS-ALIST associates view names with their SQL definition, which might
224+
be empty for already existing views. Create only the views for which we
225+
have an SQL definition."
226+
(unless (eq :all views-alist)
227+
(let ((views (remove-if #'null views-alist :key #'cdr)))
228+
(when views
229+
(loop :for (name . def) :in views
230+
:for sql := (destructuring-bind (schema . v-name) name
231+
(format nil
232+
"CREATE VIEW ~s.~s AS ~a"
233+
schema v-name def))
234+
:do (progn
235+
(log-message :info "MS SQL: ~a" sql)
236+
(mssql-query sql)))))))
237+
238+
(defun drop-ms-views (views-alist)
239+
"See `create-ms-views' for VIEWS-ALIST description. This time we DROP the
240+
views to clean out after our work."
241+
(unless (eq :all views-alist)
242+
(let ((views (remove-if #'null views-alist :key #'cdr)))
243+
(when views
244+
(let ((sql
245+
(with-output-to-string (sql)
246+
(format sql "DROP VIEW ")
247+
(loop :for view-definition :in views
248+
:for i :from 0
249+
:do (destructuring-bind (name . def) view-definition
250+
(declare (ignore def))
251+
(format sql
252+
"~@[, ~]~s.~s"
253+
(not (zerop i)) (car name) (cdr name)))))))
254+
(log-message :info "PostgreSQL Source: ~a" sql)
255+
(mssql-query sql))))))

src/sources/mssql/mssql.lisp

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,30 +72,63 @@
7272
including
7373
excluding)
7474
"MS SQL introspection to prepare the migration."
75-
(declare (ignore materialize-views only-tables))
75+
(declare (ignore only-tables))
7676
(with-stats-collection ("fetch meta data"
7777
:use-result-as-rows t
7878
:use-result-as-read t
7979
:section :pre)
80-
(with-connection (*mssql-db* (source-db mssql))
81-
(list-all-columns catalog
82-
:including including
83-
:excluding excluding)
80+
(with-connection (*mssql-db* (source-db mssql))
81+
;; If asked to MATERIALIZE VIEWS, now is the time to create them in MS
82+
;; SQL, when given definitions rather than existing view names.
83+
(when (and materialize-views (not (eq :all materialize-views)))
84+
(create-ms-views materialize-views))
85+
86+
(list-all-columns catalog
87+
:including including
88+
:excluding excluding)
89+
90+
;; fetch view (and their columns) metadata, covering comments too
91+
(let* ((view-names (unless (eq :all materialize-views)
92+
(mapcar #'car materialize-views)))
93+
(including
94+
(loop :for (schema-name . view-name) :in view-names
95+
:do (let* ((schema-name (or schema-name "dbo"))
96+
(schema-entry
97+
(or (assoc schema-name including :test #'string=)
98+
(progn (push (cons schema-name nil) including)
99+
(assoc schema-name including
100+
:test #'string=)))))
101+
(push-to-end view-name (cdr schema-entry))))))
102+
(cond (view-names
103+
(list-all-columns catalog
104+
:including including
105+
:table-type :view))
84106

85-
(when create-indexes
86-
(list-all-indexes catalog
87-
:including including
88-
:excluding excluding))
107+
((eq :all materialize-views)
108+
(list-all-columns catalog :table-type :view))))
89109

90-
(when foreign-keys
91-
(list-all-fkeys catalog
110+
(when create-indexes
111+
(list-all-indexes catalog
92112
:including including
93113
:excluding excluding))
94114

95-
;; return how many objects we're going to deal with in total
96-
;; for stats collection
97-
(+ (count-tables catalog) (count-indexes catalog))))
115+
(when foreign-keys
116+
(list-all-fkeys catalog
117+
:including including
118+
:excluding excluding))
119+
120+
;; return how many objects we're going to deal with in total
121+
;; for stats collection
122+
(+ (count-tables catalog) (count-indexes catalog))))
98123

99124
;; be sure to return the catalog itself
100125
catalog)
101126

127+
128+
(defmethod cleanup ((mssql copy-mssql) (catalog catalog) &key materialize-views)
129+
"When there is a PostgreSQL error at prepare-pgsql-database step, we might
130+
need to clean-up any view created in the MS SQL connection for the
131+
migration purpose."
132+
(when materialize-views
133+
(with-connection (*mssql-db* (source-db mssql))
134+
(drop-ms-views materialize-views))))

0 commit comments

Comments
 (0)