Skip to content

Commit a4a52db

Browse files
committed
Improve SQLite support for autoincrement and sequences.
It turns out that SQLite only creates an entry in its sqlite_sequence catalogs when some data make it to a table using a sequence, not at create table time. It means that pgloader must do some more catalog querying to figure out if a column is "autoincrement", and apparently the only way to get to the information is to parse the SQL statement given in the sqlite_master table. Fixes #882.
1 parent 204a011 commit a4a52db

File tree

2 files changed

+48
-9
lines changed

2 files changed

+48
-9
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
select sql from sqlite_master where name = '~a'

src/sources/sqlite/sqlite-schema.lisp

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,47 @@
6767
(loop for (name) in (sqlite:execute-to-list db sql)
6868
collect name)))
6969

70+
(defun find-sequence (db table-name column-name)
71+
"Find if table-name.column-name is attached to a sequence in
72+
sqlite_sequence catalog."
73+
(let* ((sql (format nil (sql "/sqlite/find-sequence.sql") table-name))
74+
(seq (sqlite:execute-single db sql)))
75+
(when (and seq (not (zerop seq)))
76+
;; magic marker for `apply-casting-rules'
77+
(log-message :notice "SQLite column ~a.~a uses a sequence"
78+
table-name column-name)
79+
seq)))
80+
81+
(defun find-auto-increment-in-create-sql (db table-name column-name)
82+
"The sqlite_sequence catalog is only created when some content has been
83+
added to the table. So we might fail to FIND-SEQUENCE, and still need to
84+
consider the column has an autoincrement. Parse the SQL definition of the
85+
table to find out."
86+
(let* ((sql (format nil (sql "/sqlite/get-create-table.sql") table-name))
87+
(create-table (sqlite:execute-single db sql))
88+
(open-paren (+ 1 (position #\( create-table)))
89+
(close-paren (position #\) create-table :from-end t))
90+
(coldefs
91+
(mapcar (lambda (def) (string-trim (list #\Space) def))
92+
(split-sequence:split-sequence #\,
93+
create-table
94+
:start open-paren
95+
:end close-paren))))
96+
(loop :for coldef :in coldefs
97+
:do (let* ((words (mapcar (lambda (w) (string-trim '(#\" #\') w))
98+
(split-sequence:split-sequence #\Space coldef)))
99+
(colname (first words))
100+
(props (rest words)))
101+
(when (and (string= colname column-name)
102+
(member "autoincrement" props :test #'string-equal))
103+
;; we know the target column has no sequence because we
104+
;; looked into that first by calling find-sequence, and we
105+
;; only call find-auto-increment-in-create-sql when
106+
;; find-sequence failed to find anything.
107+
(log-message :notice "SQLite column ~a.~a is autoincrement, but has no sequence"
108+
table-name column-name)
109+
(return t))))))
110+
70111
(defun list-columns (table &key db-has-sequences (db *sqlite-db*) )
71112
"Return the list of columns found in TABLE-NAME."
72113
(let* ((table-name (table-source-name table))
@@ -85,17 +126,14 @@
85126
pk-id)))
86127
(when (and db-has-sequences
87128
(not (zerop pk-id))
88-
(string-equal (coldef-ctype field) "integer"))
129+
(string-equal (coldef-ctype field) "integer")
130+
(or (find-sequence db table-name name)
131+
(find-auto-increment-in-create-sql db
132+
table-name
133+
name)))
89134
;; then it might be an auto_increment, which we know by
90135
;; looking at the sqlite_sequence catalog
91-
(let* ((sql
92-
(format nil (sql "/sqlite/find-sequence.sql") table-name))
93-
(seq (sqlite:execute-single db sql)))
94-
(when (and seq (not (zerop seq)))
95-
;; magic marker for `apply-casting-rules'
96-
(log-message :notice "SQLite column ~a.~a uses a sequence"
97-
table-name name)
98-
(setf (coldef-extra field) :auto-increment))))
136+
(setf (coldef-extra field) :auto-increment))
99137
(add-field table field)))))
100138

101139
(defun list-all-columns (schema

0 commit comments

Comments
 (0)