LCOV - differential code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - connect.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 71.7 % 350 251 99 251
Current Date: 2023-04-08 15:15:32 Functions: 90.9 % 11 10 1 10
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a