From 8f92cc5a7dc54c22d2d986db3b59eeae5c56c1a3 Mon Sep 17 00:00:00 2001 From: Dimitri Fontaine Date: Mon, 29 May 2017 12:42:12 +0200 Subject: [PATCH] Fix our SQL parser. In order to support custom SQL files with several queries and psql like advanced \i feature, we have our own internal SQL parser in pgloader. The PostgreSQL variant of SQL is pretty complex and allows dollar-quoting and other subtleties that we need to take care of. Here we fix the case when we have a dollar sign ($) as part of a single quoted text (such as a regexp), so both not a new dollar-quoting tag and a part of a quoted text being read. In passing we also fix reading double-quoted identifiers, even when they contain a dollar sign. After all the following is totally supported by PostgreSQL: create table dollar("$id" serial, foo text); select "$id", foo from dollar; Fix #561. --- src/utils/read-sql-files.lisp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/utils/read-sql-files.lisp b/src/utils/read-sql-files.lisp index f2bbbe4..0e26c7b 100644 --- a/src/utils/read-sql-files.lisp +++ b/src/utils/read-sql-files.lisp @@ -116,7 +116,14 @@ Another test case for the classic quotes: (#\' (case (parser-state state) (:eat (setf (parser-state state) :eqt)) (:esc (setf (parser-state state) :eqt)) - (:eqt (setf (parser-state state) :eat))) + (:eqt (setf (parser-state state) :eat)) + (:tag + (progn + ;; a tag name can't contain a single-quote + ;; get back to previous state + (let ((tag (pop-current-tag state))) + (format (parser-stream state) "$~a" tag)) + (reset-state state)))) (write-char char (parser-stream state))) @@ -134,6 +141,7 @@ Another test case for the classic quotes: ;; we act depending on the NEW state (case (parser-state state) (:eat (write-char char (parser-stream state))) + (:edq (write-char char (parser-stream state))) (:tag (push-new-tag state)) @@ -157,7 +165,7 @@ Another test case for the classic quotes: (:eat (setf (parser-state state) :eoq)) (otherwise (write-char char (parser-stream state))))) - (otherwise (cond ((member (parser-state state) '(:eat :eqt)) + (otherwise (cond ((member (parser-state state) '(:eat :eqt :edq)) (write-char char (parser-stream state))) ;; see @@ -175,9 +183,9 @@ Another test case for the classic quotes: (extend-current-tag state char) (progn - ;; not a tag actually: remove the - ;; parser-tags entry and push back its - ;; contents to the main output stream + ;; not a tag actually: remove the + ;; parser-tags entry and push back its + ;; contents to the main output stream (let ((tag (pop-current-tag state))) (format (parser-stream state) "$~a~c"