diff --git a/pgloader.1.md b/pgloader.1.md index 773f88f..4d82c57 100644 --- a/pgloader.1.md +++ b/pgloader.1.md @@ -890,6 +890,13 @@ The `csv` format command accepts the following clauses and options: when they are to be found within the data fields themselves. Defaults to *double-quote*. + - *csv escape mode* + + Takes either the special value *quote* (the default) or *following* + and allows the CSV parser to parse either only escaped field + separator or any character (including CSV data) when using the + *following* value. + - *fields terminated by* Takes a single character as argument, which must be found inside diff --git a/src/parsers/command-csv.lisp b/src/parsers/command-csv.lisp index 67c44f6..69214c2 100644 --- a/src/parsers/command-csv.lisp +++ b/src/parsers/command-csv.lisp @@ -69,6 +69,10 @@ escaped-quote-name separator)) +(defrule escape-mode-quote "quote" (:constant :quote)) +(defrule escape-mode-following "following" (:constant :following)) +(defrule escape-mode (or escape-mode-quote escape-mode-following)) + (defrule option-fields-escaped-by (and kw-fields kw-escaped kw-by escaped-quote) (:lambda (esc) (bind (((_ _ _ sep) esc)) @@ -94,6 +98,11 @@ (defrule option-trim-unquoted-blanks (and kw-trim kw-unquoted kw-blanks) (:constant (cons :trim-blanks t))) +(defrule option-csv-escape-mode (and kw-csv kw-escape kw-mode escape-mode) + (:lambda (term) + (bind (((_ _ _ escape-mode) term)) + (cons :escape-mode escape-mode)))) + (defrule csv-option (or option-batch-rows option-batch-size option-batch-concurrency @@ -107,7 +116,8 @@ option-fields-escaped-by option-fields-terminated-by option-trim-unquoted-blanks - option-keep-unquoted-blanks)) + option-keep-unquoted-blanks + option-csv-escape-mode)) (defrule another-csv-option (and comma csv-option) (:lambda (source) diff --git a/src/parsers/command-keywords.lisp b/src/parsers/command-keywords.lisp index 0bc91ca..3f49045 100644 --- a/src/parsers/command-keywords.lisp +++ b/src/parsers/command-keywords.lisp @@ -71,6 +71,8 @@ (def-keyword-rule "by") (def-keyword-rule "escaped") (def-keyword-rule "terminated") + (def-keyword-rule "escape") + (def-keyword-rule "mode") (def-keyword-rule "nullif") (def-keyword-rule "blank") (def-keyword-rule "trim") diff --git a/src/sources/csv/csv.lisp b/src/sources/csv/csv.lisp index 15f459b..374fd54 100644 --- a/src/sources/csv/csv.lisp +++ b/src/sources/csv/csv.lisp @@ -57,6 +57,9 @@ (escape :accessor csv-escape ; CSV quote escaping :initarg :escape ; :initform cl-csv:*quote-escape*) + (escape-mode :accessor csv-escape-mode ; CSV quote escaping mode + :initarg :escape-mode ; + :initform cl-csv::*escape-mode*) (trim-blanks :accessor csv-trim-blanks ; CSV blank and NULLs :initarg :trim-blanks ; :initform t)) @@ -156,6 +159,7 @@ :separator (csv-separator csv) :quote (csv-quote csv) :escape (csv-escape csv) + :escape-mode (csv-escape-mode csv) :unquoted-empty-string-is-nil t :quoted-empty-string-is-nil nil :trim-outer-whitespace (csv-trim-blanks csv)