LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - connect.c (source / functions) Hit Total Coverage
Test: PostgreSQL 15devel Lines: 266 326 81.6 %
Date: 2021-12-05 02:08:31 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         222 : ecpg_actual_connection_init(void)
      24             : {
      25         222 :     pthread_key_create(&actual_connection_key, NULL);
      26         222 : }
      27             : 
      28             : void
      29       11036 : ecpg_pthreads_init(void)
      30             : {
      31       11036 :     pthread_once(&actual_connection_key_once, ecpg_actual_connection_init);
      32       11036 : }
      33             : #endif
      34             : 
      35             : static struct connection *
      36        2096 : ecpg_get_connection_nr(const char *connection_name)
      37             : {
      38        2096 :     struct connection *ret = NULL;
      39             : 
      40        2096 :     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         170 :         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        7318 :         for (con = all_connections; con != NULL; con = con->next)
      63             :         {
      64        6958 :             if (strcmp(connection_name, con->name) == 0)
      65        1566 :                 break;
      66             :         }
      67        1926 :         ret = con;
      68             :     }
      69             : 
      70        2096 :     return ret;
      71             : }
      72             : 
      73             : struct connection *
      74       15612 : ecpg_get_connection(const char *connection_name)
      75             : {
      76       15612 :     struct connection *ret = NULL;
      77             : 
      78       15612 :     if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
      79             :     {
      80             : #ifdef ENABLE_THREAD_SAFETY
      81       13974 :         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       13974 :         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        1638 :         pthread_mutex_lock(&connections_mutex);
     100             : #endif
     101             : 
     102        1638 :         ret = ecpg_get_connection_nr(connection_name);
     103             : 
     104             : #ifdef ENABLE_THREAD_SAFETY
     105        1638 :         pthread_mutex_unlock(&connections_mutex);
     106             : #endif
     107             :     }
     108             : 
     109       15612 :     return ret;
     110             : }
     111             : 
     112             : static void
     113         504 : ecpg_finish(struct connection *act)
     114             : {
     115         504 :     if (act != NULL)
     116             :     {
     117             :         struct ECPGtype_information_cache *cache,
     118             :                    *ptr;
     119             : 
     120         504 :         ecpg_deallocate_all_conn(0, ECPG_COMPAT_PGSQL, act);
     121         504 :         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         504 :         if (act == all_connections)
     130         316 :             all_connections = act->next;
     131             :         else
     132             :         {
     133             :             struct connection *con;
     134             : 
     135         882 :             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         504 :         if (pthread_getspecific(actual_connection_key) == act)
     142         504 :             pthread_setspecific(actual_connection_key, all_connections);
     143             : #endif
     144         504 :         if (actual_connection == act)
     145         316 :             actual_connection = all_connections;
     146             : 
     147         504 :         ecpg_log("ecpg_finish: connection %s closed\n", act->name ? act->name : "(null)");
     148             : 
     149        9728 :         for (cache = act->cache_head; cache; ptr = cache, cache = cache->next, ecpg_free(ptr));
     150         504 :         ecpg_free(act->name);
     151         504 :         ecpg_free(act);
     152             :         /* delete cursor variables when last connection gets closed */
     153         504 :         if (all_connections == NULL)
     154             :         {
     155             :             struct var_list *iv_ptr;
     156             : 
     157         340 :             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         504 : }
     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         538 : ECPGconnect(int lineno, int c, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
     272             : {
     273         538 :     struct sqlca_t *sqlca = ECPGget_sqlca();
     274         538 :     enum COMPAT_MODE compat = c;
     275             :     struct connection *this;
     276             :     int         i,
     277         538 :                 connect_params = 0;
     278         538 :     char       *dbname = name ? ecpg_strdup(name, lineno) : NULL,
     279         538 :                *host = NULL,
     280             :                *tmp,
     281         538 :                *port = NULL,
     282         538 :                *realname = NULL,
     283         538 :                *options = NULL;
     284             :     const char **conn_keywords;
     285             :     const char **conn_values;
     286             : 
     287         538 :     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         538 :     ecpg_init_sqlca(sqlca);
     296             : 
     297             :     /*
     298             :      * clear auto_mem structure because some error handling functions might
     299             :      * access it
     300             :      */
     301         538 :     ecpg_clear_auto_mem();
     302             : 
     303         538 :     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         538 :     if (dbname == NULL && connection_name == NULL)
     322           0 :         connection_name = "DEFAULT";
     323             : 
     324             : #if ENABLE_THREAD_SAFETY
     325         538 :     ecpg_pthreads_init();
     326             : #endif
     327             : 
     328             :     /* check if the identifier is unique */
     329         538 :     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         530 :     if ((this = (struct connection *) ecpg_alloc(sizeof(struct connection), lineno)) == NULL)
     338             :     {
     339           0 :         ecpg_free(dbname);
     340           0 :         return false;
     341             :     }
     342             : 
     343         530 :     if (dbname != NULL)
     344             :     {
     345             :         /* get the detail information from dbname */
     346         530 :         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][/db-name][?options]
     364             :                  *------
     365             :                  */
     366          40 :                 offset += strlen("postgresql://");
     367             : 
     368          40 :                 tmp = strrchr(dbname + offset, '?');
     369          40 :                 if (tmp != NULL)    /* options given */
     370             :                 {
     371          10 :                     options = ecpg_strdup(tmp + 1, lineno);
     372          10 :                     *tmp = '\0';
     373             :                 }
     374             : 
     375          40 :                 tmp = last_dir_separator(dbname + offset);
     376          40 :                 if (tmp != NULL)    /* database name given */
     377             :                 {
     378          40 :                     if (tmp[1] != '\0') /* non-empty database name */
     379             :                     {
     380          34 :                         realname = ecpg_strdup(tmp + 1, lineno);
     381          34 :                         connect_params++;
     382             :                     }
     383          40 :                     *tmp = '\0';
     384             :                 }
     385             : 
     386          40 :                 tmp = strrchr(dbname + offset, ':');
     387          40 :                 if (tmp != NULL)    /* port number given */
     388             :                 {
     389           2 :                     *tmp = '\0';
     390           2 :                     port = ecpg_strdup(tmp + 1, lineno);
     391           2 :                     connect_params++;
     392             :                 }
     393             : 
     394          40 :                 if (strncmp(dbname, "unix:", 5) == 0)
     395             :                 {
     396             :                     /*
     397             :                      * The alternative of using "127.0.0.1" here is deprecated
     398             :                      * and undocumented; we'll keep it for backward
     399             :                      * compatibility's sake, but not extend it to allow IPv6.
     400             :                      */
     401          30 :                     if (strcmp(dbname + offset, "localhost") != 0 &&
     402           4 :                         strcmp(dbname + offset, "127.0.0.1") != 0)
     403             :                     {
     404           4 :                         ecpg_log("ECPGconnect: non-localhost access via sockets on line %d\n", lineno);
     405           4 :                         ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : ecpg_gettext("<DEFAULT>"));
     406           4 :                         if (host)
     407           0 :                             ecpg_free(host);
     408           4 :                         if (port)
     409           0 :                             ecpg_free(port);
     410           4 :                         if (options)
     411           0 :                             ecpg_free(options);
     412           4 :                         if (realname)
     413           4 :                             ecpg_free(realname);
     414           4 :                         if (dbname)
     415           4 :                             ecpg_free(dbname);
     416           4 :                         free(this);
     417           4 :                         return false;
     418             :                     }
     419             :                 }
     420             :                 else
     421             :                 {
     422          10 :                     if (*(dbname + offset) != '\0')
     423             :                     {
     424          10 :                         host = ecpg_strdup(dbname + offset, lineno);
     425          10 :                         connect_params++;
     426             :                     }
     427             :                 }
     428             :             }
     429             :         }
     430             :         else
     431             :         {
     432             :             /* old style: dbname[@server][:port] */
     433         490 :             tmp = strrchr(dbname, ':');
     434         490 :             if (tmp != NULL)    /* port number given */
     435             :             {
     436           0 :                 port = ecpg_strdup(tmp + 1, lineno);
     437           0 :                 connect_params++;
     438           0 :                 *tmp = '\0';
     439             :             }
     440             : 
     441         490 :             tmp = strrchr(dbname, '@');
     442         490 :             if (tmp != NULL)    /* host name given */
     443             :             {
     444           4 :                 host = ecpg_strdup(tmp + 1, lineno);
     445           4 :                 connect_params++;
     446           4 :                 *tmp = '\0';
     447             :             }
     448             : 
     449         490 :             if (strlen(dbname) > 0)
     450             :             {
     451         488 :                 realname = ecpg_strdup(dbname, lineno);
     452         488 :                 connect_params++;
     453             :             }
     454             :             else
     455           2 :                 realname = NULL;
     456             :         }
     457             :     }
     458             :     else
     459           0 :         realname = NULL;
     460             : 
     461             :     /*
     462             :      * Count options for the allocation done below (this may produce an
     463             :      * overestimate, it's ok).
     464             :      */
     465         526 :     if (options)
     466         296 :         for (i = 0; options[i]; i++)
     467         286 :             if (options[i] == '=')
     468          14 :                 connect_params++;
     469             : 
     470         526 :     if (user && strlen(user) > 0)
     471          42 :         connect_params++;
     472         526 :     if (passwd && strlen(passwd) > 0)
     473          36 :         connect_params++;
     474             : 
     475             :     /*
     476             :      * Allocate enough space for all connection parameters.  These allocations
     477             :      * are done before manipulating the list of connections to ease the error
     478             :      * handling on failure.
     479             :      */
     480         526 :     conn_keywords = (const char **) ecpg_alloc((connect_params + 1) * sizeof(char *), lineno);
     481         526 :     conn_values = (const char **) ecpg_alloc(connect_params * sizeof(char *), lineno);
     482         526 :     if (conn_keywords == NULL || conn_values == NULL)
     483             :     {
     484           0 :         if (host)
     485           0 :             ecpg_free(host);
     486           0 :         if (port)
     487           0 :             ecpg_free(port);
     488           0 :         if (options)
     489           0 :             ecpg_free(options);
     490           0 :         if (realname)
     491           0 :             ecpg_free(realname);
     492           0 :         if (dbname)
     493           0 :             ecpg_free(dbname);
     494           0 :         if (conn_keywords)
     495           0 :             ecpg_free(conn_keywords);
     496           0 :         if (conn_values)
     497           0 :             ecpg_free(conn_values);
     498           0 :         free(this);
     499           0 :         return false;
     500             :     }
     501             : 
     502             :     /* add connection to our list */
     503             : #ifdef ENABLE_THREAD_SAFETY
     504         526 :     pthread_mutex_lock(&connections_mutex);
     505             : #endif
     506         526 :     if (connection_name != NULL)
     507         326 :         this->name = ecpg_strdup(connection_name, lineno);
     508             :     else
     509         200 :         this->name = ecpg_strdup(realname, lineno);
     510             : 
     511         526 :     this->cache_head = NULL;
     512         526 :     this->prep_stmts = NULL;
     513             : 
     514         526 :     if (all_connections == NULL)
     515         306 :         this->next = NULL;
     516             :     else
     517         220 :         this->next = all_connections;
     518             : 
     519         526 :     all_connections = this;
     520             : #ifdef ENABLE_THREAD_SAFETY
     521         526 :     pthread_setspecific(actual_connection_key, all_connections);
     522             : #endif
     523         526 :     actual_connection = all_connections;
     524             : 
     525         570 :     ecpg_log("ECPGconnect: opening database %s on %s port %s %s%s %s%s\n",
     526             :              realname ? realname : "<DEFAULT>",
     527             :              host ? host : "<DEFAULT>",
     528           2 :              port ? (ecpg_internal_regression_mode ? "<REGRESSION_PORT>" : port) : "<DEFAULT>",
     529             :              options ? "with options " : "", options ? options : "",
     530          42 :              (user && strlen(user) > 0) ? "for user " : "", user ? user : "");
     531             : 
     532         526 :     i = 0;
     533         526 :     if (realname)
     534             :     {
     535         518 :         conn_keywords[i] = "dbname";
     536         518 :         conn_values[i] = realname;
     537         518 :         i++;
     538             :     }
     539         526 :     if (host)
     540             :     {
     541          14 :         conn_keywords[i] = "host";
     542          14 :         conn_values[i] = host;
     543          14 :         i++;
     544             :     }
     545         526 :     if (port)
     546             :     {
     547           2 :         conn_keywords[i] = "port";
     548           2 :         conn_values[i] = port;
     549           2 :         i++;
     550             :     }
     551         526 :     if (user && strlen(user) > 0)
     552             :     {
     553          42 :         conn_keywords[i] = "user";
     554          42 :         conn_values[i] = user;
     555          42 :         i++;
     556             :     }
     557         526 :     if (passwd && strlen(passwd) > 0)
     558             :     {
     559          36 :         conn_keywords[i] = "password";
     560          36 :         conn_values[i] = passwd;
     561          36 :         i++;
     562             :     }
     563         526 :     if (options)
     564             :     {
     565             :         char       *str;
     566             : 
     567             :         /*
     568             :          * The options string contains "keyword=value" pairs separated by
     569             :          * '&'s.  We must break this up into keywords and values to pass to
     570             :          * libpq (it's okay to scribble on the options string).  We ignore
     571             :          * spaces just before each keyword or value.
     572             :          */
     573          24 :         for (str = options; *str;)
     574             :         {
     575             :             int         e,
     576             :                         a;
     577             :             char       *token1,
     578             :                        *token2;
     579             : 
     580             :             /* Skip spaces before keyword */
     581          18 :             for (token1 = str; *token1 == ' '; token1++)
     582             :                  /* skip */ ;
     583             :             /* Find end of keyword */
     584         204 :             for (e = 0; token1[e] && token1[e] != '='; e++)
     585             :                  /* skip */ ;
     586          14 :             if (token1[e])      /* found "=" */
     587             :             {
     588          14 :                 token1[e] = '\0';
     589             :                 /* Skip spaces before value */
     590          14 :                 for (token2 = token1 + e + 1; *token2 == ' '; token2++)
     591             :                      /* skip */ ;
     592             :                 /* Find end of value */
     593          88 :                 for (a = 0; token2[a] && token2[a] != '&'; a++)
     594             :                      /* skip */ ;
     595          14 :                 if (token2[a])  /* found "&" => another option follows */
     596             :                 {
     597           4 :                     token2[a] = '\0';
     598           4 :                     str = token2 + a + 1;
     599             :                 }
     600             :                 else
     601          10 :                     str = token2 + a;
     602             : 
     603          14 :                 conn_keywords[i] = token1;
     604          14 :                 conn_values[i] = token2;
     605          14 :                 i++;
     606             :             }
     607             :             else
     608             :             {
     609             :                 /* Bogus options syntax ... ignore trailing garbage */
     610           0 :                 str = token1 + e;
     611             :             }
     612             :         }
     613             :     }
     614             : 
     615             :     Assert(i <= connect_params);
     616         526 :     conn_keywords[i] = NULL;    /* terminator */
     617             : 
     618         526 :     this->connection = PQconnectdbParams(conn_keywords, conn_values, 0);
     619             : 
     620         526 :     if (host)
     621          14 :         ecpg_free(host);
     622         526 :     if (port)
     623           2 :         ecpg_free(port);
     624         526 :     if (options)
     625          10 :         ecpg_free(options);
     626         526 :     if (dbname)
     627         526 :         ecpg_free(dbname);
     628         526 :     ecpg_free(conn_values);
     629         526 :     ecpg_free(conn_keywords);
     630             : 
     631         526 :     if (PQstatus(this->connection) == CONNECTION_BAD)
     632             :     {
     633          12 :         const char *errmsg = PQerrorMessage(this->connection);
     634          12 :         const char *db = realname ? realname : ecpg_gettext("<DEFAULT>");
     635             : 
     636             :         /* PQerrorMessage's result already has a trailing newline */
     637          12 :         ecpg_log("ECPGconnect: %s", errmsg);
     638             : 
     639          12 :         ecpg_finish(this);
     640             : #ifdef ENABLE_THREAD_SAFETY
     641          12 :         pthread_mutex_unlock(&connections_mutex);
     642             : #endif
     643             : 
     644          12 :         ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, db);
     645          12 :         if (realname)
     646           4 :             ecpg_free(realname);
     647             : 
     648          12 :         return false;
     649             :     }
     650             : 
     651         514 :     if (realname)
     652         514 :         ecpg_free(realname);
     653             : 
     654             : #ifdef ENABLE_THREAD_SAFETY
     655         514 :     pthread_mutex_unlock(&connections_mutex);
     656             : #endif
     657             : 
     658         514 :     this->autocommit = autocommit;
     659             : 
     660         514 :     PQsetNoticeReceiver(this->connection, &ECPGnoticeReceiver, (void *) this);
     661             : 
     662         514 :     return true;
     663             : }
     664             : 
     665             : bool
     666         522 : ECPGdisconnect(int lineno, const char *connection_name)
     667             : {
     668         522 :     struct sqlca_t *sqlca = ECPGget_sqlca();
     669             :     struct connection *con;
     670             : 
     671         522 :     if (sqlca == NULL)
     672             :     {
     673           0 :         ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
     674             :                    ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
     675           0 :         return false;
     676             :     }
     677             : 
     678             : #ifdef ENABLE_THREAD_SAFETY
     679         522 :     pthread_mutex_lock(&connections_mutex);
     680             : #endif
     681             : 
     682         522 :     if (strcmp(connection_name, "ALL") == 0)
     683             :     {
     684          64 :         ecpg_init_sqlca(sqlca);
     685         136 :         for (con = all_connections; con;)
     686             :         {
     687          72 :             struct connection *f = con;
     688             : 
     689          72 :             con = con->next;
     690          72 :             ecpg_finish(f);
     691             :         }
     692             :     }
     693             :     else
     694             :     {
     695         458 :         con = ecpg_get_connection_nr(connection_name);
     696             : 
     697         458 :         if (!ecpg_init(con, connection_name, lineno))
     698             :         {
     699             : #ifdef ENABLE_THREAD_SAFETY
     700          38 :             pthread_mutex_unlock(&connections_mutex);
     701             : #endif
     702          38 :             return false;
     703             :         }
     704             :         else
     705         420 :             ecpg_finish(con);
     706             :     }
     707             : 
     708             : #ifdef ENABLE_THREAD_SAFETY
     709         484 :     pthread_mutex_unlock(&connections_mutex);
     710             : #endif
     711             : 
     712         484 :     return true;
     713             : }
     714             : 
     715             : PGconn *
     716           0 : ECPGget_PGconn(const char *connection_name)
     717             : {
     718             :     struct connection *con;
     719             : 
     720           0 :     con = ecpg_get_connection(connection_name);
     721           0 :     if (con == NULL)
     722           0 :         return NULL;
     723             : 
     724           0 :     return con->connection;
     725             : }

Generated by: LCOV version 1.14