--- sql/pgsql/parser3pgsql.C 2021/11/03 16:27:15 1.49 +++ sql/pgsql/parser3pgsql.C 2021/11/08 08:57:16 1.51 @@ -15,7 +15,7 @@ #include #include -volatile const char * IDENT_PARSER3PGSQL_C="$Id: parser3pgsql.C,v 1.49 2021/11/03 16:27:15 moko Exp $" IDENT_PA_SQL_DRIVER_H; +volatile const char * IDENT_PARSER3PGSQL_C="$Id: parser3pgsql.C,v 1.51 2021/11/08 08:57:16 moko Exp $" IDENT_PA_SQL_DRIVER_H; // from catalog/pg_type.h #define BOOLOID 16 @@ -140,13 +140,15 @@ public: char* host=rsplit(user, '@'); char* db=lsplit(host, '/'); char* pwd=lsplit(user, ':'); - char* port=lsplit(host, ':'); char *options=lsplit(db, '?'); char* charset=0; char* datestyle=0; + char* pq_options=0; + size_t pq_options_len=options ? strlen(options) : 0; + Connection& connection=*(Connection *)services.malloc(sizeof(Connection)); *connection_ref=&connection; @@ -159,10 +161,10 @@ public: if(char *key=lsplit(&options, '&')){ if(*key){ if(char *value=lsplit(key, '=')){ - if(strcmp(key, "ClientCharset")==0){ + if(strcmp(key, "ClientCharset")==0){ // transcoding with parser toupper_str(value, value, strlen(value)); connection.client_charset=value; - } else if(strcasecmp(key, "charset")==0){ + } else if(strcasecmp(key, "charset")==0){ // transcoding with server charset=value; } else if(strcasecmp(key, "datestyle")==0){ datestyle=value; @@ -172,15 +174,31 @@ public: } else if(strcasecmp(key, "standard_conforming_strings")==0){ if(atoi(value)==0) connection.standard_conforming_strings=false; - } else - services._throw("unknown connect option" /*key*/); + } else { + if(!pq_options) { + pq_options=(char*)services.malloc_atomic(pq_options_len+2); + strcpy(pq_options, "?"); + } else { + strcat(pq_options, "&"); + } + strcat(pq_options, key); + strcat(pq_options, "="); + strcat(pq_options, value); + } } else services._throw("connect option without =value" /*key*/); } } } - connection.conn=PQsetdbLogin( (host && strcasecmp(host, "local") == 0) ? NULL /* local Unix domain socket */ : host, port, NULL, NULL, db, user, pwd); + if(host && (strchr(host, ',') || pq_options)){ // pq_options can exist only if host and db are not null + char pq_url[MAX_STRING]; + snprintf(pq_url, MAX_STRING, "postgresql://%s/%s%s", host, db ? db : "", pq_options ? pq_options : ""); + connection.conn=PQsetdbLogin(NULL, NULL, NULL, NULL, pq_url, user, pwd); + } else { + char* port=lsplit(host, ':'); + connection.conn=PQsetdbLogin( (host && strcasecmp(host, "local") == 0) ? NULL /* local Unix domain socket */ : host, port, NULL, NULL, db, user, pwd); + } if(!connection.conn) services._throw("PQsetdbLogin failed"); @@ -189,21 +207,19 @@ public: throwPQerror; if(charset){ - char statement[MAX_STRING+1]="SET CLIENT_ENCODING="; - strncat(statement, charset, MAX_STRING); - + char statement[MAX_STRING]; + snprintf(statement, MAX_STRING, "SET CLIENT_ENCODING=%s", charset); _execute_cmd(connection, statement); } if(datestyle){ - char statement[MAX_STRING+1]="SET DATESTYLE="; - strncat(statement, datestyle, MAX_STRING); - + char statement[MAX_STRING]; + snprintf(statement, MAX_STRING, "SET DATESTYLE=%s", datestyle); _execute_cmd(connection, statement); } if(!connection.autocommit) - _execute_cmd(connection, "set AUTOCOMMIT off"); + _execute_cmd(connection, "BEGIN"); } void disconnect(void *aconnection){ @@ -636,14 +652,19 @@ private: // conn client library funcs private: // conn client library funcs linking - const char *dlink(const char *dlopen_file_spec) { + const char *dlink(char *dlopen_file_spec) { if(lt_dlinit()){ if(const char* result=lt_dlerror()) return result; return "can not prepare to dynamic loading"; } - lt_dlhandle handle=lt_dlopen(dlopen_file_spec); + lt_dlhandle handle; + do { + char *next=lsplit(dlopen_file_spec, ','); + handle=lt_dlopen(dlopen_file_spec); + dlopen_file_spec=next; + } while (!handle && dlopen_file_spec); if(!handle){ if(const char* result=lt_dlerror()) @@ -657,7 +678,7 @@ private: // conn client library funcs li action; #define DLINK(name) DSLINK(name, return "function " #name " was not found") - + DLINK(PQsetdbLogin); DLINK(PQerrorMessage); DLINK(PQstatus);