mirror of
https://github.com/dimitri/pgloader.git
synced 2025-08-10 16:26:58 +02:00
Assorted fixes for SQLite.
First review the `sqlite_sequence` support so that we can still work with databases that don't have this catalog, which doesn't always exists -- it might depend on the SQLite version though. Then while at it use the sql macro to host the SQLite “queries” in their own files, enhancing the hackability of the system to some degrees. Not that much, because we have to use a lot of PGRAMA command and then the column output isn't documented with the query text itself.
This commit is contained in:
parent
20d7858e27
commit
29506e6fa6
4
src/sources/sqlite/sql/find-sequence.sql
Normal file
4
src/sources/sqlite/sql/find-sequence.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
-- params: table-name
|
||||||
|
select seq
|
||||||
|
from sqlite_sequence
|
||||||
|
where name = '~a';
|
1
src/sources/sqlite/sql/list-columns.sql
Normal file
1
src/sources/sqlite/sql/list-columns.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
PRAGMA table_info(`~a`)
|
1
src/sources/sqlite/sql/list-fkeys.sql
Normal file
1
src/sources/sqlite/sql/list-fkeys.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
PRAGMA foreign_key_list(`~a`)
|
1
src/sources/sqlite/sql/list-index-cols.sql
Normal file
1
src/sources/sqlite/sql/list-index-cols.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
PRAGMA index_info(`~a`)
|
2
src/sources/sqlite/sql/list-table-indexes.sql
Normal file
2
src/sources/sqlite/sql/list-table-indexes.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
-- params: table-name
|
||||||
|
PRAGMA index_list(`~a`)
|
6
src/sources/sqlite/sql/list-tables.sql
Normal file
6
src/sources/sqlite/sql/list-tables.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
SELECT tbl_name
|
||||||
|
FROM sqlite_master
|
||||||
|
WHERE type='table'
|
||||||
|
AND tbl_name <> 'sqlite_sequence'
|
||||||
|
~:[~*~;AND (~{~a~^~&~10t or ~})~]
|
||||||
|
~:[~*~;AND (~{~a~^~&~10t and ~})~]"
|
3
src/sources/sqlite/sql/sqlite-sequence.sql
Normal file
3
src/sources/sqlite/sql/sqlite-sequence.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
SELECT tbl_name
|
||||||
|
FROM sqlite_master
|
||||||
|
WHERE tbl_name = 'sqlite_sequence'
|
@ -10,7 +10,7 @@
|
|||||||
;;; Integration with the pgloader Source API
|
;;; Integration with the pgloader Source API
|
||||||
;;;
|
;;;
|
||||||
(defclass sqlite-connection (fd-connection)
|
(defclass sqlite-connection (fd-connection)
|
||||||
((has-sequences :accessor has-sequences)))
|
((has-sequences :initform nil :accessor has-sequences)))
|
||||||
|
|
||||||
(defmethod initialize-instance :after ((slconn sqlite-connection) &key)
|
(defmethod initialize-instance :after ((slconn sqlite-connection) &key)
|
||||||
"Assign the type slot to sqlite."
|
"Assign the type slot to sqlite."
|
||||||
@ -21,10 +21,8 @@
|
|||||||
(sqlite:connect (fd-path slconn)))
|
(sqlite:connect (fd-path slconn)))
|
||||||
(log-message :debug "CONNECTED TO ~a" (fd-path slconn))
|
(log-message :debug "CONNECTED TO ~a" (fd-path slconn))
|
||||||
(when check-has-sequences
|
(when check-has-sequences
|
||||||
(let ((sql (format nil "SELECT tbl_name
|
(let ((sql (format nil (sql "/sqlite/sqlite-sequence.sql"))))
|
||||||
FROM sqlite_master
|
(log-message :sql "SQLite: ~a" sql)
|
||||||
WHERE tbl_name = 'sqlite_sequence'")))
|
|
||||||
(log-message :info "SQLite: ~a" sql)
|
|
||||||
(when (sqlite:execute-single (conn-handle slconn) sql)
|
(when (sqlite:execute-single (conn-handle slconn) sql)
|
||||||
(setf (has-sequences slconn) t))))
|
(setf (has-sequences slconn) t))))
|
||||||
slconn)
|
slconn)
|
||||||
@ -60,24 +58,19 @@
|
|||||||
including
|
including
|
||||||
excluding)
|
excluding)
|
||||||
"Return the list of tables found in SQLITE-DB."
|
"Return the list of tables found in SQLITE-DB."
|
||||||
(let ((sql (format nil "SELECT tbl_name
|
(let ((sql (format nil (sql "/sqlite/list-tables.sql")
|
||||||
FROM sqlite_master
|
|
||||||
WHERE type='table'
|
|
||||||
AND tbl_name <> 'sqlite_sequence'
|
|
||||||
~:[~*~;AND (~{~a~^~&~10t or ~})~]
|
|
||||||
~:[~*~;AND (~{~a~^~&~10t and ~})~]"
|
|
||||||
including ; do we print the clause?
|
including ; do we print the clause?
|
||||||
(filter-list-to-where-clause including nil)
|
(filter-list-to-where-clause including nil)
|
||||||
excluding ; do we print the clause?
|
excluding ; do we print the clause?
|
||||||
(filter-list-to-where-clause excluding t))))
|
(filter-list-to-where-clause excluding t))))
|
||||||
(log-message :info "~a" sql)
|
(log-message :sql "~a" sql)
|
||||||
(loop for (name) in (sqlite:execute-to-list db sql)
|
(loop for (name) in (sqlite:execute-to-list db sql)
|
||||||
collect name)))
|
collect name)))
|
||||||
|
|
||||||
(defun list-columns (table &key db-has-sequences (db *sqlite-db*) )
|
(defun list-columns (table &key db-has-sequences (db *sqlite-db*) )
|
||||||
"Return the list of columns found in TABLE-NAME."
|
"Return the list of columns found in TABLE-NAME."
|
||||||
(let* ((table-name (table-source-name table))
|
(let* ((table-name (table-source-name table))
|
||||||
(sql (format nil "PRAGMA table_info(`~a`)" table-name)))
|
(sql (format nil (sql "/sqlite/list-columns.sql") table-name)))
|
||||||
(loop :for (ctid name type nullable default pk-id)
|
(loop :for (ctid name type nullable default pk-id)
|
||||||
:in (sqlite:execute-to-list db sql)
|
:in (sqlite:execute-to-list db sql)
|
||||||
:do (let* ((ctype (normalize type))
|
:do (let* ((ctype (normalize type))
|
||||||
@ -95,8 +88,8 @@
|
|||||||
(string-equal (coldef-ctype field) "integer"))
|
(string-equal (coldef-ctype field) "integer"))
|
||||||
;; then it might be an auto_increment, which we know by
|
;; then it might be an auto_increment, which we know by
|
||||||
;; looking at the sqlite_sequence catalog
|
;; looking at the sqlite_sequence catalog
|
||||||
(let* ((sql (format nil "select seq from sqlite_sequence
|
(let* ((sql
|
||||||
where name = '~a';" table-name))
|
(format nil (sql "/sqlite/find-sequence.sql") table-name))
|
||||||
(seq (sqlite:execute-single db sql)))
|
(seq (sqlite:execute-single db sql)))
|
||||||
(when (and seq (not (zerop seq)))
|
(when (and seq (not (zerop seq)))
|
||||||
;; magic marker for `apply-casting-rules'
|
;; magic marker for `apply-casting-rules'
|
||||||
@ -155,16 +148,18 @@
|
|||||||
|
|
||||||
(defun list-index-cols (index-name &optional (db *sqlite-db*))
|
(defun list-index-cols (index-name &optional (db *sqlite-db*))
|
||||||
"Return the list of columns in INDEX-NAME."
|
"Return the list of columns in INDEX-NAME."
|
||||||
(let ((sql (format nil "PRAGMA index_info(`~a`)" index-name)))
|
(let ((sql (format nil (sql "/sqlite/list-index-cols.sql") index-name)))
|
||||||
(loop :for (index-pos table-pos col-name) :in (sqlite:execute-to-list db sql)
|
(loop :for (index-pos table-pos col-name) :in (sqlite:execute-to-list db sql)
|
||||||
:collect col-name)))
|
:collect col-name)))
|
||||||
|
|
||||||
(defun list-indexes (table &optional (db *sqlite-db*))
|
(defun list-indexes (table &optional (db *sqlite-db*))
|
||||||
"Return the list of indexes attached to TABLE."
|
"Return the list of indexes attached to TABLE."
|
||||||
(let* ((table-name (table-source-name table))
|
(let* ((table-name (table-source-name table))
|
||||||
(sql (format nil "PRAGMA index_list(`~a`)" table-name)))
|
(sql
|
||||||
|
(format nil (sql "/sqlite/list-table-indexes.sql") table-name)))
|
||||||
(loop
|
(loop
|
||||||
:for (seq index-name unique origin partial) :in (sqlite:execute-to-list db sql)
|
:for (seq index-name unique origin partial)
|
||||||
|
:in (sqlite:execute-to-list db sql)
|
||||||
:do (let* ((cols (list-index-cols index-name db))
|
:do (let* ((cols (list-index-cols index-name db))
|
||||||
(index (make-index :name index-name
|
(index (make-index :name index-name
|
||||||
:table table
|
:table table
|
||||||
@ -192,7 +187,8 @@
|
|||||||
(defun list-fkeys (table &optional (db *sqlite-db*))
|
(defun list-fkeys (table &optional (db *sqlite-db*))
|
||||||
"Return the list of indexes attached to TABLE."
|
"Return the list of indexes attached to TABLE."
|
||||||
(let* ((table-name (table-source-name table))
|
(let* ((table-name (table-source-name table))
|
||||||
(sql (format nil "PRAGMA foreign_key_list(`~a`)" table-name)))
|
(sql
|
||||||
|
(format nil (sql "/sqlite/list-fkeys.sql") table-name)))
|
||||||
(loop
|
(loop
|
||||||
:with fkey-table := (make-hash-table)
|
:with fkey-table := (make-hash-table)
|
||||||
:for (id seq ftable-name from to on-update on-delete match)
|
:for (id seq ftable-name from to on-update on-delete match)
|
||||||
|
10
test/sqlite-chinook-noseq.load
Normal file
10
test/sqlite-chinook-noseq.load
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
load database
|
||||||
|
from 'sqlite/Chinook_Sqlite.sqlite'
|
||||||
|
into postgresql:///pgloader
|
||||||
|
|
||||||
|
set work_mem to '16MB',
|
||||||
|
maintenance_work_mem to '512 MB',
|
||||||
|
search_path to 'chinook'
|
||||||
|
|
||||||
|
before load do
|
||||||
|
$$ create schema if not exists chinook; $$;
|
Loading…
Reference in New Issue
Block a user