Fix identifier quoting corner cases.

In cases when pgloader needs to build a new identifer from existing
ones (mainly for renaming indexes, because they are unique per-table in the
source database and unique per-schema in PostgreSQL), and we compose the new
name from already quoted strings, pgloader was doing the wrong thing.

Fix that by having a build-identifier function that may unquote parts then
re-quote properly (if needed) the new identifier.
This commit is contained in:
Dimitri Fontaine 2017-07-05 15:37:21 +02:00
parent f6cb428c6d
commit bae40d40c3
5 changed files with 34 additions and 20 deletions

View File

@ -32,7 +32,10 @@
(defpackage #:pgloader.quoting
(:use #:cl #:pgloader.params)
(:export #:apply-identifier-case))
(:export #:apply-identifier-case
#:build-identifier
#:quoted-p
#:ensure-unquoted))
(defpackage #:pgloader.catalog
(:use #:cl #:pgloader.params #:pgloader.quoting)
@ -251,6 +254,7 @@
(defpackage #:pgloader.utils
(:use #:cl
#:pgloader.params
#:pgloader.quoting
#:pgloader.catalog
#:pgloader.monitor
#:pgloader.state
@ -278,11 +282,9 @@
;; charsets
#:list-encodings-and-aliases
#:show-encodings
#:make-external-format
;; quoting
#:apply-identifier-case))
#:make-external-format))
(cl-user::export-inherited-symbols "pgloader.quoting" "pgloader.utils")
(cl-user::export-inherited-symbols "pgloader.catalog" "pgloader.utils")
(cl-user::export-inherited-symbols "pgloader.monitor" "pgloader.utils")
(cl-user::export-inherited-symbols "pgloader.state" "pgloader.utils")

View File

@ -150,10 +150,10 @@
(index-name index)
;; in the general case, we build our own index name.
(format nil "idx_~a_~a"
(table-oid (index-table index))
(index-name index))))
(index-name (apply-identifier-case index-name)))
(build-identifier "_"
"idx"
(table-oid (index-table index))
(index-name index)))))
(cond
((or (index-primary index)
(and (index-condef index) (index-unique index)))

View File

@ -98,16 +98,6 @@
(let ((table-name (table-name table)))
(format nil "^~a$" (ensure-unquoted table-name))))
(defun ensure-unquoted (identifier)
(cond ((pgloader.quoting::quoted-p identifier)
;; when the table name comes from the user (e.g. in the
;; load file) then we might have to unquote it: the
;; PostgreSQL catalogs does not store object names in
;; their quoted form.
(subseq identifier 1 (1- (length identifier))))
(t identifier)))
(defun query-table-schema (table)
"Get PostgreSQL schema name where to locate TABLE-NAME by following the
current search_path rules. A PostgreSQL connection must be opened."

View File

@ -132,7 +132,7 @@
(every (lambda (field)
(string-equal "integer" (coldef-dtype field)))
pk-fields))
(let ((pk-name (format nil "~a_pkey" (format-table-name table)))
(let ((pk-name (build-identifier "_" (format-table-name table) "pkey"))
(clist (mapcar #'coldef-name pk-fields)))
;; now forge the index and get it a name
(add-index table (make-index :name pk-name

View File

@ -46,3 +46,25 @@
(:quote (format nil "~s"
(cl-ppcre:regex-replace-all "\"" identifier "\"\"")))
(:none identifier))))
(defun ensure-unquoted (identifier)
(cond ((quoted-p identifier)
;; when the table name comes from the user (e.g. in the
;; load file) then we might have to unquote it: the
;; PostgreSQL catalogs does not store object names in
;; their quoted form.
(subseq identifier 1 (1- (length identifier))))
(t identifier)))
(defun build-identifier (sep &rest parts)
"Concatenante PARTS into a PostgreSQL identifier, with SEP in between
parts. That's useful for creating an index name from a table's oid and name."
(apply-identifier-case
(apply #'concatenate
'string
(loop :for (part . more?) :on parts
:collect (ensure-unquoted (typecase part
(string part)
(t (princ-to-string part))))
:when more? :collect sep))))