LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - connect.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 72.7 % 355 258
Test Date: 2026-07-26 08:15:28 Functions: 90.9 % 11 10
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 62.7 % 284 178

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

Generated by: LCOV version 2.0-1