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:
.
.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
.
.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\.
.
.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\.
.
.IP

View File

@ -165,11 +165,25 @@ specific clauses such as the `CAST` clause.
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*
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 *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
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 "typemod")
(def-keyword-rule "using")
(def-keyword-rule "getenv")
;; option for loading from a file
(def-keyword-rule "workers")
(def-keyword-rule "batch")
@ -361,7 +362,17 @@
(:postgresql (getenv-default "PGDATABASE" user))))
: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)
(declare (ignore into))
(destructuring-bind (&key type &allow-other-keys) target
@ -439,6 +450,20 @@
(:destructure (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
http-uri
db-connection-uri
@ -454,7 +479,8 @@
source))
(defrule database-source (and kw-load kw-database kw-from
db-connection-uri)
(or db-connection-uri
get-dburi-from-environment-variable))
(:lambda (source)
(destructuring-bind (l d f uri) source
(declare (ignore l d f))
@ -1101,7 +1127,19 @@ load database
(list :sqlite path)))))
(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)
(declare (ignore l d f))
u))
@ -1861,7 +1899,18 @@ load database
filename-matching
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)
(destructuring-bind (load csv from source) src
(declare (ignore load csv from))
@ -2017,7 +2066,18 @@ load database
filename-matching
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)
(destructuring-bind (load fixed from source) src
(declare (ignore load fixed from))
@ -2103,8 +2163,6 @@ load database
(destructuring-bind (col1 cols) source
(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)
(:lambda (src)
(destructuring-bind (load from archive source) src