From 62535cae9723afc48173ba1be65f1c7491813fc2 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 11 Feb 2021 15:05:55 -0500 Subject: [PATCH] Remove dead code in ECPGconnect(), and improve documentation. The stanza in ECPGconnect() that intended to allow specification of a Unix socket directory path in place of a port has never executed since it was committed, nearly two decades ago; the preceding strrchr() already found the last colon so there cannot be another one. The lack of complaints about that is doubtless related to the fact that no user-facing documentation suggested it was possible. Rather than try to fix that up, let's just remove the unreachable code, and instead document the way that does work to write a socket directory path, namely specifying it as a "host" option. In support of that, make another pass at clarifying the syntax documentation for ECPG connection targets, particularly documenting which things are parsed as identifiers and where to use double quotes. Rearrange some things that seemed poorly ordered, and fix a couple of minor doc errors. Kyotaro Horiguchi, per gripe from Shenhao Wang (docs changes mostly by me) Discussion: https://postgr.es/m/ae52a416bbbf459c96bab30b3038e06c@G08CNEXMBPEKD06.g08.fujitsu.local --- doc/src/sgml/ecpg.sgml | 94 ++++++++++++++++----------- src/interfaces/ecpg/ecpglib/connect.c | 48 ++++---------- 2 files changed, 67 insertions(+), 75 deletions(-) diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml index 0fef9bfcbe..9310a71166 100644 --- a/doc/src/sgml/ecpg.sgml +++ b/doc/src/sgml/ecpg.sgml @@ -120,7 +120,7 @@ EXEC SQL CONNECT TO target AS - unix:postgresql://hostname:port/dbname?options + unix:postgresql://localhost:port/dbname?options @@ -143,17 +143,26 @@ EXEC SQL CONNECT TO target AS - If you specify the connection target literally (that is, not - through a variable reference) and you don't quote the value, then - the case-insensitivity rules of normal SQL are applied. In that - case you can also double-quote the individual parameters separately - as needed. In practice, it is probably less error-prone to use a - (single-quoted) string literal or a variable reference. The - connection target DEFAULT initiates a connection + The connection target DEFAULT initiates a connection to the default database under the default user name. No separate user name or connection name can be specified in that case. + + If you specify the connection target directly (that is, not as a string + literal or variable reference), then the components of the target are + passed through normal SQL parsing; this means that, for example, + the hostname must look like one or more SQL + identifiers separated by dots, and those identifiers will be + case-folded unless double-quoted. Values of + any options must be SQL identifiers, + integers, or variable references. Of course, you can put nearly + anything into an SQL identifier by double-quoting it. + In practice, it is probably less error-prone to use a (single-quoted) + string literal or a variable reference than to write the connection + target directly. + + There are also different ways to specify the user name: @@ -201,6 +210,15 @@ EXEC SQL CONNECT TO target AS write & within a value. + + Notice that when specifying a socket connection + (with the unix: prefix), the host name must be + exactly localhost. To select a non-default + socket directory, write the directory's pathname as the value of + a host option in + the options part of the target. + + The connection-name is used to handle multiple connections in one program. It can be omitted if a @@ -210,6 +228,36 @@ EXEC SQL CONNECT TO target AS chapter). + + Here are some examples of CONNECT statements: + +EXEC SQL CONNECT TO mydb@sql.mydomain.com; + +EXEC SQL CONNECT TO tcp:postgresql://sql.mydomain.com/mydb AS myconnection USER john; + +EXEC SQL BEGIN DECLARE SECTION; +const char *target = "mydb@sql.mydomain.com"; +const char *user = "john"; +const char *passwd = "secret"; +EXEC SQL END DECLARE SECTION; + ... +EXEC SQL CONNECT TO :target USER :user USING :passwd; +/* or EXEC SQL CONNECT TO :target USER :user/:passwd; */ + + The last example makes use of the feature referred to above as + character variable references. You will see in later sections how C + variables can be used in SQL statements when you prefix them with a + colon. + + + + Be advised that the format of the connection target is not + specified in the SQL standard. So if you want to develop portable + applications, you might want to use something based on the last + example above to encapsulate the connection target string + somewhere. + + If untrusted users have access to a database that has not adopted a secure schema usage pattern, @@ -221,36 +269,6 @@ EXEC SQL CONNECT TO target AS false); after connecting. This consideration is not specific to ECPG; it applies to every interface for executing arbitrary SQL commands. - - - Here are some examples of CONNECT statements: - -EXEC SQL CONNECT TO mydb@sql.mydomain.com; - -EXEC SQL CONNECT TO unix:postgresql://sql.mydomain.com/mydb AS myconnection USER john; - -EXEC SQL BEGIN DECLARE SECTION; -const char *target = "mydb@sql.mydomain.com"; -const char *user = "john"; -const char *passwd = "secret"; -EXEC SQL END DECLARE SECTION; - ... -EXEC SQL CONNECT TO :target USER :user USING :passwd; -/* or EXEC SQL CONNECT TO :target USER :user/:passwd; */ - - The last form makes use of the variant referred to above as - character variable reference. You will see in later sections how C - variables can be used in SQL statements when you prefix them with a - colon. - - - - Be advised that the format of the connection target is not - specified in the SQL standard. So if you want to develop portable - applications, you might want to use something based on the last - example above to encapsulate the connection target string - somewhere. - diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c index 6b0a3067e6..60564b176c 100644 --- a/src/interfaces/ecpg/ecpglib/connect.c +++ b/src/interfaces/ecpg/ecpglib/connect.c @@ -360,8 +360,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p /*------ * new style: - * :postgresql://server[:port|:/unixsocket/path:] - * [/db-name][?options] + * :postgresql://server[:port][/db-name][?options] *------ */ offset += strlen("postgresql://"); @@ -385,46 +384,22 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p } tmp = strrchr(dbname + offset, ':'); - if (tmp != NULL) /* port number or Unix socket path given */ + if (tmp != NULL) /* port number given */ { - char *tmp2; - *tmp = '\0'; - if ((tmp2 = strchr(tmp + 1, ':')) != NULL) - { - *tmp2 = '\0'; - host = ecpg_strdup(tmp + 1, lineno); - connect_params++; - if (strncmp(dbname, "unix:", 5) != 0) - { - ecpg_log("ECPGconnect: socketname %s given for TCP connection on line %d\n", host, lineno); - ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : ecpg_gettext("")); - if (host) - ecpg_free(host); - - /* - * port not set yet if (port) ecpg_free(port); - */ - if (options) - ecpg_free(options); - if (realname) - ecpg_free(realname); - if (dbname) - ecpg_free(dbname); - free(this); - return false; - } - } - else - { - port = ecpg_strdup(tmp + 1, lineno); - connect_params++; - } + port = ecpg_strdup(tmp + 1, lineno); + connect_params++; } if (strncmp(dbname, "unix:", 5) == 0) { - if (strcmp(dbname + offset, "localhost") != 0 && strcmp(dbname + offset, "127.0.0.1") != 0) + /* + * The alternative of using "127.0.0.1" here is deprecated + * and undocumented; we'll keep it for backward + * compatibility's sake, but not extend it to allow IPv6. + */ + if (strcmp(dbname + offset, "localhost") != 0 && + strcmp(dbname + offset, "127.0.0.1") != 0) { ecpg_log("ECPGconnect: non-localhost access via sockets on line %d\n", lineno); ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : ecpg_gettext("")); @@ -450,7 +425,6 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p connect_params++; } } - } } else