LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - connect.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 266 342 77.8 %
Date: 2020-01-26 00:06:34 Functions: 10 11 90.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* src/interfaces/ecpg/ecpglib/connect.c */
       2             : 
       3             : #define POSTGRES_ECPG_INTERNAL
       4             : #include "postgres_fe.h"
       5             : 
       6             : #include "ecpg-pthread-win32.h"
       7             : #include "ecpgerrno.h"
       8             : #include "ecpglib.h"
       9             : #include "ecpglib_extern.h"
      10             : #include "ecpgtype.h"
      11             : #include "sqlca.h"
      12             : 
      13             : #ifdef ENABLE_THREAD_SAFETY
      14             : static pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER;
      15             : static pthread_key_t actual_connection_key;
      16             : static pthread_once_t actual_connection_key_once = PTHREAD_ONCE_INIT;
      17             : #endif
      18             : static struct connection *actual_connection = NULL;
      19             : static struct connection *all_connections = NULL;
      20             : 
      21             : #ifdef ENABLE_THREAD_SAFETY
      22             : static void
      23         218 : ecpg_actual_connection_init(void)
      24             : {
      25         218 :     pthread_key_create(&actual_connection_key, NULL);
      26         218 : }
      27             : 
      28             : void
      29       10900 : ecpg_pthreads_init(void)
      30             : {
      31       10900 :     pthread_once(&actual_connection_key_once, ecpg_actual_connection_init);
      32       10900 : }
      33             : #endif
      34             : 
      35             : static struct connection *
      36        1956 : ecpg_get_connection_nr(const char *connection_name)
      37             : {
      38        1956 :     struct connection *ret = NULL;
      39             : 
      40        1956 :     if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
      41             :     {
      42             : #ifdef ENABLE_THREAD_SAFETY
      43         170 :         ret = pthread_getspecific(actual_connection_key);
      44             : 
      45             :         /*
      46             :          * if no connection in TSD for this thread, get the global default
      47             :          * connection and hope the user knows what they're doing (i.e. using
      48             :          * their own mutex to protect that connection from concurrent accesses
      49             :          */
      50             :         /* if !ret then  we  got the connection from TSD */
      51         178 :         if (NULL == ret)
      52             :             /* no TSD connection, going for global */
      53           8 :             ret = actual_connection;
      54             : #else
      55             :         ret = actual_connection;
      56             : #endif
      57             :     }
      58             :     else
      59             :     {
      60             :         struct connection *con;
      61             : 
      62        7508 :         for (con = all_connections; con != NULL; con = con->next)
      63             :         {
      64        7148 :             if (strcmp(connection_name, con->name) == 0)
      65        1426 :                 break;
      66             :         }
      67        1786 :         ret = con;
      68             :     }
      69             : 
      70        1956 :     return ret;
      71             : }
      72             : 
      73             : struct connection *
      74       15392 : ecpg_get_connection(const char *connection_name)
      75             : {
      76       15392 :     struct connection *ret = NULL;
      77             : 
      78       15392 :     if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
      79             :     {
      80             : #ifdef ENABLE_THREAD_SAFETY
      81       13898 :         ret = pthread_getspecific(actual_connection_key);
      82             : 
      83             :         /*
      84             :          * if no connection in TSD for this thread, get the global default
      85             :          * connection and hope the user knows what they're doing (i.e. using
      86             :          * their own mutex to protect that connection from concurrent accesses
      87             :          */
      88             :         /* if !ret then  we  got the connection from TSD */
      89       14122 :         if (NULL == ret)
      90             :             /* no TSD connection here either, using global */
      91         224 :             ret = actual_connection;
      92             : #else
      93             :         ret = actual_connection;
      94             : #endif
      95             :     }
      96             :     else
      97             :     {
      98             : #ifdef ENABLE_THREAD_SAFETY
      99        1494 :         pthread_mutex_lock(&connections_mutex);
     100             : #endif
     101             : 
     102        1494 :         ret = ecpg_get_connection_nr(connection_name);
     103             : 
     104             : #ifdef ENABLE_THREAD_SAFETY
     105        1494 :         pthread_mutex_unlock(&connections_mutex);
     106             : #endif
     107             :     }
     108             : 
     109       15392 :     return ret;
     110             : }
     111             : 
     112             : static void
     113         500 : ecpg_finish(struct connection *act)
     114             : {
     115         500 :     if (act != NULL)
     116             :     {
     117             :         struct ECPGtype_information_cache *cache,
     118             :                    *ptr;
     119             : 
     120         500 :         ecpg_deallocate_all_conn(0, ECPG_COMPAT_PGSQL, act);
     121         500 :         PQfinish(act->connection);
     122             : 
     123             :         /*
     124             :          * no need to lock connections_mutex - we're always called by
     125             :          * ECPGdisconnect or ECPGconnect, which are holding the lock
     126             :          */
     127             : 
     128             :         /* remove act from the list */
     129         500 :         if (act == all_connections)
     130         312 :             all_connections = act->next;
     131             :         else
     132             :         {
     133             :             struct connection *con;
     134             : 
     135         978 :             for (con = all_connections; con->next && con->next != act; con = con->next);
     136         188 :             if (con->next)
     137         188 :                 con->next = act->next;
     138             :         }
     139             : 
     140             : #ifdef ENABLE_THREAD_SAFETY
     141         500 :         if (pthread_getspecific(actual_connection_key) == act)
     142         500 :             pthread_setspecific(actual_connection_key, all_connections);
     143             : #endif
     144         500 :         if (actual_connection == act)
     145         312 :             actual_connection = all_connections;
     146             : 
     147         500 :         ecpg_log("ecpg_finish: connection %s closed\n", act->name ? act->name : "(null)");
     148             : 
     149        9412 :         for (cache = act->cache_head; cache; ptr = cache, cache = cache->next, ecpg_free(ptr));
     150         500 :         ecpg_free(act->name);
     151         500 :         ecpg_free(act);
     152             :         /* delete cursor variables when last connection gets closed */
     153         500 :         if (all_connections == NULL)
     154             :         {
     155             :             struct var_list *iv_ptr;
     156             : 
     157         336 :             for (; ivlist; iv_ptr = ivlist, ivlist = ivlist->next, ecpg_free(iv_ptr));
     158             :         }
     159             :     }
     160             :     else
     161           0 :         ecpg_log("ecpg_finish: called an extra time\n");
     162         500 : }
     163             : 
     164             : bool
     165         164 : ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
     166             : {
     167         164 :     struct connection *con = ecpg_get_connection(connection_name);
     168             :     PGresult   *results;
     169             : 
     170         164 :     if (!ecpg_init(con, connection_name, lineno))
     171           0 :         return false;
     172             : 
     173         164 :     ecpg_log("ECPGsetcommit on line %d: action \"%s\"; connection \"%s\"\n", lineno, mode, con->name);
     174             : 
     175         164 :     if (con->autocommit && strncmp(mode, "off", strlen("off")) == 0)
     176             :     {
     177           0 :         if (PQtransactionStatus(con->connection) == PQTRANS_IDLE)
     178             :         {
     179           0 :             results = PQexec(con->connection, "begin transaction");
     180           0 :             if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL))
     181           0 :                 return false;
     182           0 :             PQclear(results);
     183             :         }
     184           0 :         con->autocommit = false;
     185             :     }
     186         164 :     else if (!con->autocommit && strncmp(mode, "on", strlen("on")) == 0)
     187             :     {
     188         152 :         if (PQtransactionStatus(con->connection) != PQTRANS_IDLE)
     189             :         {
     190           0 :             results = PQexec(con->connection, "commit");
     191           0 :             if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL))
     192           0 :                 return false;
     193           0 :             PQclear(results);
     194             :         }
     195         152 :         con->autocommit = true;
     196             :     }
     197             : 
     198         164 :     return true;
     199             : }
     200             : 
     201             : bool
     202           8 : ECPGsetconn(int lineno, const char *connection_name)
     203             : {
     204           8 :     struct connection *con = ecpg_get_connection(connection_name);
     205             : 
     206           8 :     if (!ecpg_init(con, connection_name, lineno))
     207           0 :         return false;
     208             : 
     209             : #ifdef ENABLE_THREAD_SAFETY
     210           8 :     pthread_setspecific(actual_connection_key, con);
     211             : #else
     212             :     actual_connection = con;
     213             : #endif
     214           8 :     return true;
     215             : }
     216             : 
     217             : 
     218             : static void
     219           8 : ECPGnoticeReceiver(void *arg, const PGresult *result)
     220             : {
     221           8 :     char       *sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE);
     222           8 :     char       *message = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
     223           8 :     struct sqlca_t *sqlca = ECPGget_sqlca();
     224             :     int         sqlcode;
     225             : 
     226           8 :     if (sqlca == NULL)
     227             :     {
     228           0 :         ecpg_log("out of memory");
     229           0 :         return;
     230             :     }
     231             : 
     232             :     (void) arg;                 /* keep the compiler quiet */
     233           8 :     if (sqlstate == NULL)
     234           0 :         sqlstate = ECPG_SQLSTATE_ECPG_INTERNAL_ERROR;
     235             : 
     236           8 :     if (message == NULL)        /* Shouldn't happen, but need to be sure */
     237           0 :         message = ecpg_gettext("empty message text");
     238             : 
     239             :     /* these are not warnings */
     240           8 :     if (strncmp(sqlstate, "00", 2) == 0)
     241           4 :         return;
     242             : 
     243           4 :     ecpg_log("ECPGnoticeReceiver: %s\n", message);
     244             : 
     245             :     /* map to SQLCODE for backward compatibility */
     246           4 :     if (strcmp(sqlstate, ECPG_SQLSTATE_INVALID_CURSOR_NAME) == 0)
     247           0 :         sqlcode = ECPG_WARNING_UNKNOWN_PORTAL;
     248           4 :     else if (strcmp(sqlstate, ECPG_SQLSTATE_ACTIVE_SQL_TRANSACTION) == 0)
     249           0 :         sqlcode = ECPG_WARNING_IN_TRANSACTION;
     250           4 :     else if (strcmp(sqlstate, ECPG_SQLSTATE_NO_ACTIVE_SQL_TRANSACTION) == 0)
     251           0 :         sqlcode = ECPG_WARNING_NO_TRANSACTION;
     252           4 :     else if (strcmp(sqlstate, ECPG_SQLSTATE_DUPLICATE_CURSOR) == 0)
     253           0 :         sqlcode = ECPG_WARNING_PORTAL_EXISTS;
     254             :     else
     255           4 :         sqlcode = 0;
     256             : 
     257           4 :     strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate));
     258           4 :     sqlca->sqlcode = sqlcode;
     259           4 :     sqlca->sqlwarn[2] = 'W';
     260           4 :     sqlca->sqlwarn[0] = 'W';
     261             : 
     262           4 :     strncpy(sqlca->sqlerrm.sqlerrmc, message, sizeof(sqlca->sqlerrm.sqlerrmc));
     263           4 :     sqlca->sqlerrm.sqlerrmc[sizeof(sqlca->sqlerrm.sqlerrmc) - 1] = 0;
     264           4 :     sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
     265             : 
     266           4 :     ecpg_log("raising sqlcode %d\n", sqlcode);
     267             : }
     268             : 
     269             : /* this contains some quick hacks, needs to be cleaned up, but it works */
     270             : bool
     271         534 : ECPGconnect(int lineno, int c, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
     272             : {
     273         534 :     struct sqlca_t *sqlca = ECPGget_sqlca();
     274         534 :     enum COMPAT_MODE compat = c;
     275             :     struct connection *this;
     276             :     int         i,
     277         534 :                 connect_params = 0;
     278         534 :     char       *dbname = name ? ecpg_strdup(name, lineno) : NULL,
     279         534 :                *host = NULL,
     280             :                *tmp,
     281         534 :                *port = NULL,
     282         534 :                *realname = NULL,
     283         534 :                *options = NULL;
     284             :     const char **conn_keywords;
     285             :     const char **conn_values;
     286             : 
     287         534 :     if (sqlca == NULL)
     288             :     {
     289           0 :         ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
     290             :                    ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
     291           0 :         ecpg_free(dbname);
     292           0 :         return false;
     293             :     }
     294             : 
     295         534 :     ecpg_init_sqlca(sqlca);
     296             : 
     297             :     /*
     298             :      * clear auto_mem structure because some error handling functions might
     299             :      * access it
     300             :      */
     301         534 :     ecpg_clear_auto_mem();
     302             : 
     303         534 :     if (INFORMIX_MODE(compat))
     304             :     {
     305             :         char       *envname;
     306             : 
     307             :         /*
     308             :          * Informix uses an environment variable DBPATH that overrides the
     309             :          * connection parameters given here. We do the same with PG_DBPATH as
     310             :          * the syntax is different.
     311             :          */
     312          24 :         envname = getenv("PG_DBPATH");
     313          24 :         if (envname)
     314             :         {
     315           0 :             ecpg_free(dbname);
     316           0 :             dbname = ecpg_strdup(envname, lineno);
     317             :         }
     318             : 
     319             :     }
     320             : 
     321         534 :     if (dbname == NULL && connection_name == NULL)
     322           0 :         connection_name = "DEFAULT";
     323             : 
     324             : #if ENABLE_THREAD_SAFETY
     325         534 :     ecpg_pthreads_init();
     326             : #endif
     327             : 
     328             :     /* check if the identifier is unique */
     329         534 :     if (ecpg_get_connection(connection_name))
     330             :     {
     331           8 :         ecpg_free(dbname);
     332           8 :         ecpg_log("ECPGconnect: connection identifier %s is already in use\n",
     333             :                  connection_name);
     334           8 :         return false;
     335             :     }
     336             : 
     337         526 :     if ((this = (struct connection *) ecpg_alloc(sizeof(struct connection), lineno)) == NULL)
     338             :     {
     339           0 :         ecpg_free(dbname);
     340           0 :         return false;
     341             :     }
     342             : 
     343         526 :     if (dbname != NULL)
     344             :     {
     345             :         /* get the detail information from dbname */
     346         526 :         if (strncmp(dbname, "tcp:", 4) == 0 || strncmp(dbname, "unix:", 5) == 0)
     347          36 :         {
     348          40 :             int         offset = 0;
     349             : 
     350             :             /*
     351             :              * only allow protocols tcp and unix
     352             :              */
     353          40 :             if (strncmp(dbname, "tcp:", 4) == 0)
     354          10 :                 offset = 4;
     355          30 :             else if (strncmp(dbname, "unix:", 5) == 0)
     356          30 :                 offset = 5;
     357             : 
     358          40 :             if (strncmp(dbname + offset, "postgresql://", strlen("postgresql://")) == 0)
     359             :             {
     360             : 
     361             :                 /*------
     362             :                  * new style:
     363             :                  *  <tcp|unix>:postgresql://server[:port|:/unixsocket/path:]
     364             :                  *  [/db-name][?options]
     365             :                  *------
     366             :                  */
     367          40 :                 offset += strlen("postgresql://");
     368             : 
     369          40 :                 tmp = strrchr(dbname + offset, '?');
     370          40 :                 if (tmp != NULL)    /* options given */
     371             :                 {
     372           6 :                     options = ecpg_strdup(tmp + 1, lineno);
     373           6 :                     *tmp = '\0';
     374             :                 }
     375             : 
     376          40 :                 tmp = last_dir_separator(dbname + offset);
     377          40 :                 if (tmp != NULL)    /* database name given */
     378             :                 {
     379          40 :                     if (tmp[1] != '\0') /* non-empty database name */
     380             :                     {
     381          34 :                         realname = ecpg_strdup(tmp + 1, lineno);
     382          34 :                         connect_params++;
     383             :                     }
     384          40 :                     *tmp = '\0';
     385             :                 }
     386             : 
     387          40 :                 tmp = strrchr(dbname + offset, ':');
     388          40 :                 if (tmp != NULL)    /* port number or Unix socket path given */
     389             :                 {
     390             :                     char       *tmp2;
     391             : 
     392           2 :                     *tmp = '\0';
     393           2 :                     if ((tmp2 = strchr(tmp + 1, ':')) != NULL)
     394             :                     {
     395           0 :                         *tmp2 = '\0';
     396           0 :                         host = ecpg_strdup(tmp + 1, lineno);
     397           0 :                         connect_params++;
     398           0 :                         if (strncmp(dbname, "unix:", 5) != 0)
     399             :                         {
     400           0 :                             ecpg_log("ECPGconnect: socketname %s given for TCP connection on line %d\n", host, lineno);
     401           0 :                             ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : ecpg_gettext("<DEFAULT>"));
     402           0 :                             if (host)
     403           0 :                                 ecpg_free(host);
     404             : 
     405             :                             /*
     406             :                              * port not set yet if (port) ecpg_free(port);
     407             :                              */
     408           0 :                             if (options)
     409           0 :                                 ecpg_free(options);
     410           0 :                             if (realname)
     411           0 :                                 ecpg_free(realname);
     412           0 :                             if (dbname)
     413           0 :                                 ecpg_free(dbname);
     414           0 :                             free(this);
     415           0 :                             return false;
     416             :                         }
     417             :                     }
     418             :                     else
     419             :                     {
     420           2 :                         port = ecpg_strdup(tmp + 1, lineno);
     421           2 :                         connect_params++;
     422             :                     }
     423             :                 }
     424             : 
     425          40 :                 if (strncmp(dbname, "unix:", 5) == 0)
     426             :                 {
     427          30 :                     if (strcmp(dbname + offset, "localhost") != 0 && strcmp(dbname + offset, "127.0.0.1") != 0)
     428             :                     {
     429           4 :                         ecpg_log("ECPGconnect: non-localhost access via sockets on line %d\n", lineno);
     430           4 :                         ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : ecpg_gettext("<DEFAULT>"));
     431           4 :                         if (host)
     432           0 :                             ecpg_free(host);
     433           4 :                         if (port)
     434           0 :                             ecpg_free(port);
     435           4 :                         if (options)
     436           0 :                             ecpg_free(options);
     437           4 :                         if (realname)
     438           4 :                             ecpg_free(realname);
     439           4 :                         if (dbname)
     440           4 :                             ecpg_free(dbname);
     441           4 :                         free(this);
     442           4 :                         return false;
     443             :                     }
     444             :                 }
     445             :                 else
     446             :                 {
     447          10 :                     if (*(dbname + offset) != '\0')
     448             :                     {
     449          10 :                         host = ecpg_strdup(dbname + offset, lineno);
     450          10 :                         connect_params++;
     451             :                     }
     452             :                 }
     453             : 
     454             :             }
     455             :         }
     456             :         else
     457             :         {
     458             :             /* old style: dbname[@server][:port] */
     459         486 :             tmp = strrchr(dbname, ':');
     460         486 :             if (tmp != NULL)    /* port number given */
     461             :             {
     462           0 :                 port = ecpg_strdup(tmp + 1, lineno);
     463           0 :                 connect_params++;
     464           0 :                 *tmp = '\0';
     465             :             }
     466             : 
     467         486 :             tmp = strrchr(dbname, '@');
     468         486 :             if (tmp != NULL)    /* host name given */
     469             :             {
     470           4 :                 host = ecpg_strdup(tmp + 1, lineno);
     471           4 :                 connect_params++;
     472           4 :                 *tmp = '\0';
     473             :             }
     474             : 
     475         486 :             if (strlen(dbname) > 0)
     476             :             {
     477         480 :                 realname = ecpg_strdup(dbname, lineno);
     478         480 :                 connect_params++;
     479             :             }
     480             :             else
     481           6 :                 realname = NULL;
     482             :         }
     483             :     }
     484             :     else
     485           0 :         realname = NULL;
     486             : 
     487             :     /* add connection to our list */
     488             : #ifdef ENABLE_THREAD_SAFETY
     489         522 :     pthread_mutex_lock(&connections_mutex);
     490             : #endif
     491         522 :     if (connection_name != NULL)
     492         322 :         this->name = ecpg_strdup(connection_name, lineno);
     493             :     else
     494         200 :         this->name = ecpg_strdup(realname, lineno);
     495             : 
     496         522 :     this->cache_head = NULL;
     497         522 :     this->prep_stmts = NULL;
     498             : 
     499         522 :     if (all_connections == NULL)
     500         306 :         this->next = NULL;
     501             :     else
     502         216 :         this->next = all_connections;
     503             : 
     504         522 :     all_connections = this;
     505             : #ifdef ENABLE_THREAD_SAFETY
     506         522 :     pthread_setspecific(actual_connection_key, all_connections);
     507             : #endif
     508         522 :     actual_connection = all_connections;
     509             : 
     510         570 :     ecpg_log("ECPGconnect: opening database %s on %s port %s %s%s %s%s\n",
     511             :              realname ? realname : "<DEFAULT>",
     512             :              host ? host : "<DEFAULT>",
     513           2 :              port ? (ecpg_internal_regression_mode ? "<REGRESSION_PORT>" : port) : "<DEFAULT>",
     514             :              options ? "with options " : "", options ? options : "",
     515          46 :              (user && strlen(user) > 0) ? "for user " : "", user ? user : "");
     516             : 
     517             :     /* count options (this may produce an overestimate, it's ok) */
     518         522 :     if (options)
     519         214 :         for (i = 0; options[i]; i++)
     520         208 :             if (options[i] == '=')
     521          10 :                 connect_params++;
     522             : 
     523         522 :     if (user && strlen(user) > 0)
     524          46 :         connect_params++;
     525         522 :     if (passwd && strlen(passwd) > 0)
     526          40 :         connect_params++;
     527             : 
     528             :     /* allocate enough space for all connection parameters */
     529         522 :     conn_keywords = (const char **) ecpg_alloc((connect_params + 1) * sizeof(char *), lineno);
     530         522 :     conn_values = (const char **) ecpg_alloc(connect_params * sizeof(char *), lineno);
     531         522 :     if (conn_keywords == NULL || conn_values == NULL)
     532             :     {
     533           0 :         if (host)
     534           0 :             ecpg_free(host);
     535           0 :         if (port)
     536           0 :             ecpg_free(port);
     537           0 :         if (options)
     538           0 :             ecpg_free(options);
     539           0 :         if (realname)
     540           0 :             ecpg_free(realname);
     541           0 :         if (dbname)
     542           0 :             ecpg_free(dbname);
     543           0 :         if (conn_keywords)
     544           0 :             ecpg_free(conn_keywords);
     545           0 :         if (conn_values)
     546           0 :             ecpg_free(conn_values);
     547           0 :         free(this);
     548           0 :         return false;
     549             :     }
     550             : 
     551         522 :     i = 0;
     552         522 :     if (realname)
     553             :     {
     554         510 :         conn_keywords[i] = "dbname";
     555         510 :         conn_values[i] = realname;
     556         510 :         i++;
     557             :     }
     558         522 :     if (host)
     559             :     {
     560          14 :         conn_keywords[i] = "host";
     561          14 :         conn_values[i] = host;
     562          14 :         i++;
     563             :     }
     564         522 :     if (port)
     565             :     {
     566           2 :         conn_keywords[i] = "port";
     567           2 :         conn_values[i] = port;
     568           2 :         i++;
     569             :     }
     570         522 :     if (user && strlen(user) > 0)
     571             :     {
     572          46 :         conn_keywords[i] = "user";
     573          46 :         conn_values[i] = user;
     574          46 :         i++;
     575             :     }
     576         522 :     if (passwd && strlen(passwd) > 0)
     577             :     {
     578          40 :         conn_keywords[i] = "password";
     579          40 :         conn_values[i] = passwd;
     580          40 :         i++;
     581             :     }
     582         522 :     if (options)
     583             :     {
     584             :         char       *str;
     585             : 
     586             :         /*
     587             :          * The options string contains "keyword=value" pairs separated by
     588             :          * '&'s.  We must break this up into keywords and values to pass to
     589             :          * libpq (it's okay to scribble on the options string).  We ignore
     590             :          * spaces just before each keyword or value.
     591             :          */
     592          16 :         for (str = options; *str;)
     593             :         {
     594             :             int         e,
     595             :                         a;
     596             :             char       *token1,
     597             :                        *token2;
     598             : 
     599             :             /* Skip spaces before keyword */
     600          14 :             for (token1 = str; *token1 == ' '; token1++)
     601             :                  /* skip */ ;
     602             :             /* Find end of keyword */
     603         160 :             for (e = 0; token1[e] && token1[e] != '='; e++)
     604             :                  /* skip */ ;
     605          10 :             if (token1[e])      /* found "=" */
     606             :             {
     607          10 :                 token1[e] = '\0';
     608             :                 /* Skip spaces before value */
     609          10 :                 for (token2 = token1 + e + 1; *token2 == ' '; token2++)
     610             :                      /* skip */ ;
     611             :                 /* Find end of value */
     612          50 :                 for (a = 0; token2[a] && token2[a] != '&'; a++)
     613             :                      /* skip */ ;
     614          10 :                 if (token2[a])  /* found "&" => another option follows */
     615             :                 {
     616           4 :                     token2[a] = '\0';
     617           4 :                     str = token2 + a + 1;
     618             :                 }
     619             :                 else
     620           6 :                     str = token2 + a;
     621             : 
     622          10 :                 conn_keywords[i] = token1;
     623          10 :                 conn_values[i] = token2;
     624          10 :                 i++;
     625             :             }
     626             :             else
     627             :             {
     628             :                 /* Bogus options syntax ... ignore trailing garbage */
     629           0 :                 str = token1 + e;
     630             :             }
     631             :         }
     632             :     }
     633             : 
     634             :     Assert(i <= connect_params);
     635         522 :     conn_keywords[i] = NULL;    /* terminator */
     636             : 
     637         522 :     this->connection = PQconnectdbParams(conn_keywords, conn_values, 0);
     638             : 
     639         522 :     if (host)
     640          14 :         ecpg_free(host);
     641         522 :     if (port)
     642           2 :         ecpg_free(port);
     643         522 :     if (options)
     644           6 :         ecpg_free(options);
     645         522 :     if (dbname)
     646         522 :         ecpg_free(dbname);
     647         522 :     ecpg_free(conn_values);
     648         522 :     ecpg_free(conn_keywords);
     649             : 
     650         522 :     if (PQstatus(this->connection) == CONNECTION_BAD)
     651             :     {
     652          16 :         const char *errmsg = PQerrorMessage(this->connection);
     653          16 :         const char *db = realname ? realname : ecpg_gettext("<DEFAULT>");
     654             : 
     655          16 :         ecpg_log("ECPGconnect: could not open database: %s\n", errmsg);
     656             : 
     657          16 :         ecpg_finish(this);
     658             : #ifdef ENABLE_THREAD_SAFETY
     659          16 :         pthread_mutex_unlock(&connections_mutex);
     660             : #endif
     661             : 
     662          16 :         ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, db);
     663          16 :         if (realname)
     664           4 :             ecpg_free(realname);
     665             : 
     666          16 :         return false;
     667             :     }
     668             : 
     669         506 :     if (realname)
     670         506 :         ecpg_free(realname);
     671             : 
     672             : #ifdef ENABLE_THREAD_SAFETY
     673         506 :     pthread_mutex_unlock(&connections_mutex);
     674             : #endif
     675             : 
     676         506 :     this->autocommit = autocommit;
     677             : 
     678         506 :     PQsetNoticeReceiver(this->connection, &ECPGnoticeReceiver, (void *) this);
     679             : 
     680         506 :     return true;
     681             : }
     682             : 
     683             : bool
     684         522 : ECPGdisconnect(int lineno, const char *connection_name)
     685             : {
     686         522 :     struct sqlca_t *sqlca = ECPGget_sqlca();
     687             :     struct connection *con;
     688             : 
     689         522 :     if (sqlca == NULL)
     690             :     {
     691           0 :         ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
     692             :                    ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
     693           0 :         return false;
     694             :     }
     695             : 
     696             : #ifdef ENABLE_THREAD_SAFETY
     697         522 :     pthread_mutex_lock(&connections_mutex);
     698             : #endif
     699             : 
     700         522 :     if (strcmp(connection_name, "ALL") == 0)
     701             :     {
     702          60 :         ecpg_init_sqlca(sqlca);
     703         124 :         for (con = all_connections; con;)
     704             :         {
     705          64 :             struct connection *f = con;
     706             : 
     707          64 :             con = con->next;
     708          64 :             ecpg_finish(f);
     709             :         }
     710             :     }
     711             :     else
     712             :     {
     713         462 :         con = ecpg_get_connection_nr(connection_name);
     714             : 
     715         462 :         if (!ecpg_init(con, connection_name, lineno))
     716             :         {
     717             : #ifdef ENABLE_THREAD_SAFETY
     718          42 :             pthread_mutex_unlock(&connections_mutex);
     719             : #endif
     720          42 :             return false;
     721             :         }
     722             :         else
     723         420 :             ecpg_finish(con);
     724             :     }
     725             : 
     726             : #ifdef ENABLE_THREAD_SAFETY
     727         480 :     pthread_mutex_unlock(&connections_mutex);
     728             : #endif
     729             : 
     730         480 :     return true;
     731             : }
     732             : 
     733             : PGconn *
     734           0 : ECPGget_PGconn(const char *connection_name)
     735             : {
     736             :     struct connection *con;
     737             : 
     738           0 :     con = ecpg_get_connection(connection_name);
     739           0 :     if (con == NULL)
     740           0 :         return NULL;
     741             : 
     742           0 :     return con->connection;
     743             : }

Generated by: LCOV version 1.13