Implement GETENV facility for reading FROM and INTO clauses.

It might be important to be able to use the exact same pgloader commands
file but adapt its source and target depending on the environment where
the command is to be run (production, development, staging, etc).

Introduce the new sub-clause GETENV 'variable-name' to that effect.

The regression test facility that we have now isn't nearly sophisticated
enough to support this, so the feature isn't yet covered.
This commit is contained in:
Dimitri Fontaine 2014-07-24 18:28:59 +02:00
parent 798ae1e1a8
commit 368dd88b48
3 changed files with 91 additions and 7 deletions

View File

@ -184,12 +184,24 @@ The main clauses are the \fBLOAD\fR, \fBFROM\fR, \fBINTO\fR and \fBWITH\fR claus
Some clauses are common to all commands: Some clauses are common to all commands:
. .
.IP "\(bu" 4 .IP "\(bu" 4
\fIFROM\fR
.
.IP
The \fIFROM\fR clause specifies where to read the data from, and each command introduces its own variant of sources\. For instance, the \fICSV\fR source supports \fBinline\fR, \fBstdin\fR, a filename, a quoted filename, and a \fIFILENAME MATCHING\fR clause (see above); whereas the \fIMySQL\fR source only supports a MySQL database URI specification\.
.
.IP
In all cases, the \fIFROM\fR clause is able to read its value from an environment variable when using the form \fBGETENV \'varname\'\fR\.
.
.IP "\(bu" 4
\fIINTO\fR \fIINTO\fR
. .
.IP .IP
The PostgreSQL connection URI must contains the name of the target table where to load the data into\. That table must have already been created in PostgreSQL, and the name might be schema qualified\. The PostgreSQL connection URI must contains the name of the target table where to load the data into\. That table must have already been created in PostgreSQL, and the name might be schema qualified\.
. .
.IP .IP
The \fIINTO\fR target database connection URI can be parsed from the value of an environment variable when using the form \fBGETENV \'varname\'\fR\.
.
.IP
Then \fIINTO\fR option also supports an optional comma separated list of target columns, which are either the name of an input \fIfield\fR or the whitespace separated list of the target column name, its PostgreSQL data type and a \fIUSING\fR expression\. Then \fIINTO\fR option also supports an optional comma separated list of target columns, which are either the name of an input \fIfield\fR or the whitespace separated list of the target column name, its PostgreSQL data type and a \fIUSING\fR expression\.
. .
.IP .IP

View File

@ -165,11 +165,25 @@ specific clauses such as the `CAST` clause.
Some clauses are common to all commands: Some clauses are common to all commands:
- *FROM*
The *FROM* clause specifies where to read the data from, and each
command introduces its own variant of sources. For instance, the *CSV*
source supports `inline`, `stdin`, a filename, a quoted filename, and a
*FILENAME MATCHING* clause (see above); whereas the *MySQL* source only
supports a MySQL database URI specification.
In all cases, the *FROM* clause is able to read its value from an
environment variable when using the form `GETENV 'varname'`.
- *INTO* - *INTO*
The PostgreSQL connection URI must contains the name of the target table The PostgreSQL connection URI must contains the name of the target table
where to load the data into. That table must have already been created where to load the data into. That table must have already been created
in PostgreSQL, and the name might be schema qualified. in PostgreSQL, and the name might be schema qualified.
The *INTO* target database connection URI can be parsed from the value
of an environment variable when using the form `GETENV 'varname'`.
Then *INTO* option also supports an optional comma separated list of Then *INTO* option also supports an optional comma separated list of
target columns, which are either the name of an input *field* or the target columns, which are either the name of an input *field* or the

View File

@ -91,6 +91,7 @@
(def-keyword-rule "default") (def-keyword-rule "default")
(def-keyword-rule "typemod") (def-keyword-rule "typemod")
(def-keyword-rule "using") (def-keyword-rule "using")
(def-keyword-rule "getenv")
;; option for loading from a file ;; option for loading from a file
(def-keyword-rule "workers") (def-keyword-rule "workers")
(def-keyword-rule "batch") (def-keyword-rule "batch")
@ -361,7 +362,17 @@
(:postgresql (getenv-default "PGDATABASE" user)))) (:postgresql (getenv-default "PGDATABASE" user))))
:table-name table-name))))) :table-name table-name)))))
(defrule target (and kw-into db-connection-uri) (defrule get-dburi-from-environment-variable (and kw-getenv name)
(:lambda (p-e-v)
(destructuring-bind (g varname) p-e-v
(declare (ignore g))
(let ((connstring (getenv-default varname)))
(unless connstring
(error "Environment variable ~s is unset." varname))
(parse 'db-connection-uri connstring)))))
(defrule target (and kw-into (or db-connection-uri
get-dburi-from-environment-variable))
(:destructure (into target) (:destructure (into target)
(declare (ignore into)) (declare (ignore into))
(destructuring-bind (&key type &allow-other-keys) target (destructuring-bind (&key type &allow-other-keys) target
@ -439,6 +450,20 @@
(:destructure (prefix url) (:destructure (prefix url)
(list :http (concatenate 'string prefix url)))) (list :http (concatenate 'string prefix url))))
(defrule maybe-quoted-filename-or-http-uri (or http-uri maybe-quoted-filename))
(defrule get-filename-or-http-uri-from-environment-variable (and kw-getenv name)
(:lambda (p-e-v)
(destructuring-bind (g varname) p-e-v
(declare (ignore g))
(let ((connstring (getenv-default varname)))
(unless connstring
(error "Environment variable ~s is unset." varname))
(parse 'maybe-quoted-filename-or-http-uri connstring)))))
(defrule filename-or-http-uri (or get-filename-or-http-uri-from-environment-variable
maybe-quoted-filename-or-http-uri))
(defrule source-uri (or stdin (defrule source-uri (or stdin
http-uri http-uri
db-connection-uri db-connection-uri
@ -454,7 +479,8 @@
source)) source))
(defrule database-source (and kw-load kw-database kw-from (defrule database-source (and kw-load kw-database kw-from
db-connection-uri) (or db-connection-uri
get-dburi-from-environment-variable))
(:lambda (source) (:lambda (source)
(destructuring-bind (l d f uri) source (destructuring-bind (l d f uri) source
(declare (ignore l d f)) (declare (ignore l d f))
@ -1101,7 +1127,19 @@ load database
(list :sqlite path))))) (list :sqlite path)))))
(defrule sqlite-uri (or sqlite-db-uri http-uri maybe-quoted-filename)) (defrule sqlite-uri (or sqlite-db-uri http-uri maybe-quoted-filename))
(defrule sqlite-source (and kw-load kw-database kw-from sqlite-uri)
(defrule get-sqlite-uri-from-environment-variable (and kw-getenv name)
(:lambda (p-e-v)
(destructuring-bind (g varname) p-e-v
(declare (ignore g))
(let ((connstring (getenv-default varname)))
(unless connstring
(error "Environment variable ~s is unset." varname))
(parse 'sqlite-uri connstring)))))
(defrule sqlite-source (and kw-load kw-database kw-from
(or get-sqlite-uri-from-environment-variable
sqlite-uri))
(:destructure (l d f u) (:destructure (l d f u)
(declare (ignore l d f)) (declare (ignore l d f))
u)) u))
@ -1861,7 +1899,18 @@ load database
filename-matching filename-matching
maybe-quoted-filename)) maybe-quoted-filename))
(defrule csv-source (and kw-load kw-csv kw-from csv-file-source) (defrule get-csv-file-source-from-environment-variable (and kw-getenv name)
(:lambda (p-e-v)
(destructuring-bind (g varname) p-e-v
(declare (ignore g))
(let ((connstring (getenv-default varname)))
(unless connstring
(error "Environment variable ~s is unset." varname))
(parse 'csv-file-source connstring)))))
(defrule csv-source (and kw-load kw-csv kw-from
(or get-csv-file-source-from-environment-variable
csv-file-source))
(:lambda (src) (:lambda (src)
(destructuring-bind (load csv from source) src (destructuring-bind (load csv from source) src
(declare (ignore load csv from)) (declare (ignore load csv from))
@ -2017,7 +2066,18 @@ load database
filename-matching filename-matching
maybe-quoted-filename)) maybe-quoted-filename))
(defrule fixed-source (and kw-load kw-fixed kw-from fixed-file-source) (defrule get-fixed-file-source-from-environment-variable (and kw-getenv name)
(:lambda (p-e-v)
(destructuring-bind (g varname) p-e-v
(declare (ignore g))
(let ((connstring (getenv-default varname)))
(unless connstring
(error "Environment variable ~s is unset." varname))
(parse 'fixed-file-source connstring)))))
(defrule fixed-source (and kw-load kw-fixed kw-from
(or get-fixed-file-source-from-environment-variable
fixed-file-source))
(:lambda (src) (:lambda (src)
(destructuring-bind (load fixed from source) src (destructuring-bind (load fixed from source) src
(declare (ignore load fixed from)) (declare (ignore load fixed from))
@ -2103,8 +2163,6 @@ load database
(destructuring-bind (col1 cols) source (destructuring-bind (col1 cols) source
(cons :commands (list* col1 cols))))) (cons :commands (list* col1 cols)))))
(defrule filename-or-http-uri (or http-uri maybe-quoted-filename))
(defrule archive-source (and kw-load kw-archive kw-from filename-or-http-uri) (defrule archive-source (and kw-load kw-archive kw-from filename-or-http-uri)
(:lambda (src) (:lambda (src)
(destructuring-bind (load from archive source) src (destructuring-bind (load from archive source) src