First steps toward MS SQL compatibility.

This commit is contained in:
Dimitri Fontaine 2014-11-09 00:09:42 +01:00
parent 4c87ece82a
commit 6473a892d4
3 changed files with 135 additions and 1 deletions

View File

@ -31,7 +31,7 @@
#:trivial-backtrace ; For --debug cli usage #:trivial-backtrace ; For --debug cli usage
#:cl-markdown ; To produce the website #:cl-markdown ; To produce the website
#:metabang-bind ; the bind macro #:metabang-bind ; the bind macro
;#:cl-mssql ; M$ SQL connectivity #:mssql ; M$ SQL connectivity
) )
:components :components
((:module "src" ((:module "src"

View File

@ -291,6 +291,31 @@
#:copy-database #:copy-database
#:list-tables)) #:list-tables))
(defpackage #:pgloader.mssql
(:use #:cl
#:pgloader.params #:pgloader.utils
#:pgloader.sources #:pgloader.queue)
(:import-from #:pgloader.transforms #:precision #:scale)
(:import-from #:pgloader.pgsql
#:with-pgsql-transaction
#:pgsql-execute
#:pgsql-execute-with-timing
#:apply-identifier-case
#:create-tables
#:truncate-tables
#:format-pgsql-column
#:make-pgsql-index
#:index-table-name
#:format-pgsql-create-index
#:create-indexes-in-kernel)
(:export #:copy-mssql
#:*mssql-default-cast-rules*
#:map-rows
#:copy-to
#:copy-from
#:copy-database
#:list-tables))
(defpackage #:pgloader.syslog (defpackage #:pgloader.syslog
(:use #:cl #:pgloader.params #:pgloader.utils) (:use #:cl #:pgloader.params #:pgloader.utils)
(:import-from #:pgloader.pgsql (:import-from #:pgloader.pgsql

109
src/sources/mssql.lisp Normal file
View File

@ -0,0 +1,109 @@
;;;
;;; Tools to handle the MS SQL Database
;;;
(in-package :pgloader.mssql)
(defvar *mssql-db* nil
"The MS SQL database connection handler.")
;;;
;;; Specific implementation of schema migration, see the API in
;;; src/pgsql/schema.lisp
;;;
(defstruct (mssql-column
(:constructor make-mssql-column
(schema table-name name type default nullable
character-maximum-length
numeric-precision
numeric-precision-radix
numeric-scale
datetime-precision
character-set-name
collation-name)))
schema table-name name type default nullable
character-maximum-length
numeric-precision numeric-precision-radix numeric-scale
datetime-precision
character-set-name collation-name)
;;;
;;; Those functions are to be called from withing an already established
;;; MS SQL Connection.
;;;
;;; Tools to get MS SQL table and columns definitions and transform them to
;;; PostgreSQL CREATE TABLE statements, and run those.
;;;
(defvar *table-type* '((:table . "BASE TABLE")
(:view . "VIEW"))
"Associate internal table type symbol with what's found in MS SQL
information_schema.tables.table_type column.")
(defun list-all-columns (&key
(dbname *my-dbname*)
(table-type :table)
&aux
(table-type-name (cdr (assoc table-type *table-type*))))
(loop
:with result := nil
:for (schema table-name name type default nullable
character-maximum-length
numeric-precision numeric-precision-radix numeric-scale
datetime-precision
character-set-name collation-name)
:in
(mssql:query (format nil "
select c.table_schema,
c.table_name,
c.column_name,
c.data_type,
c.column_default,
c.is_nullable,
c.CHARACTER_MAXIMUM_LENGTH,
c.NUMERIC_PRECISION,
c.NUMERIC_PRECISION_RADIX,
c.NUMERIC_SCALE,
c.DATETIME_PRECISION,
c.CHARACTER_SET_NAME,
c.COLLATION_NAME
from information_schema.columns c
join information_schema.tables t
on c.table_schema = t.table_schema
and c.table_name = t.table_name
where c.table_catalog = '~a'
and t.table_type = '~a'
order by table_schema, table_name, ordinal_position"
dbname
table-type-name)
:connection *mssql-db*)
:do
(let* ((s-entry (assoc schema result :test 'equal))
(t-entry (when s-entry
(assoc table-name (cdr s-entry) :test 'equal)))
(column
(make-mssql-column
schema table-name name type default nullable
character-maximum-length
numeric-precision numeric-precision-radix numeric-scale
datetime-precision
character-set-name collation-name)))
(if s-entry
(if t-entry
(push column (cdr t-entry))
(push (cons table-name (list column)) (cdr s-entry)))
(push (cons schema (list (cons table-name (list column)))) result)))
:finally
;; we did push, we need to reverse here
(return (reverse
(loop :for (schema . tables) :in result
:collect
(cons schema
(reverse (loop :for (table-name . cols) :in tables
:collect (cons table-name (reverse cols))))))))))