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 17:13:01 Functions: 90.9 % 11 10 1 10
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 71.7 % 350 251 99 251
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 90.9 % 11 10 1 10

 Age         Owner                  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
 6965 meskes                     27 CBC          56 : ecpg_actual_connection_init(void)
                                 28                 : {
 6797 bruce                      29              56 :     pthread_key_create(&actual_connection_key, NULL);
 6965 meskes                     30              56 : }
                                 31                 : 
                                 32                 : void
 6031 bruce                      33            6301 : ecpg_pthreads_init(void)
                                 34                 : {
 6094 meskes                     35            6301 :     pthread_once(&actual_connection_key_once, ecpg_actual_connection_init);
                                 36            6301 : }
                                 37                 : #endif
                                 38                 : 
                                 39                 : static struct connection *
 7222                            40             519 : ecpg_get_connection_nr(const char *connection_name)
                                 41                 : {
 7188 bruce                      42             519 :     struct connection *ret = NULL;
                                 43                 : 
                                 44             519 :     if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
                                 45                 :     {
                                 46                 : #ifdef ENABLE_THREAD_SAFETY
  299 tgl                        47              40 :         ecpg_pthreads_init();   /* ensure actual_connection_key is valid */
                                 48                 : 
 6965 meskes                     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                 :          */
  299 tgl                        56              40 :         if (ret == NULL)
                                 57                 :             /* no TSD connection, going for global */
 6569 meskes                     58               1 :             ret = actual_connection;
                                 59                 : #else
                                 60                 :         ret = actual_connection;
                                 61                 : #endif
                                 62                 :     }
                                 63                 :     else
                                 64                 :     {
                                 65                 :         struct connection *con;
                                 66                 : 
 7188 bruce                      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                 : 
 2061 peter_e                    75             519 :     return ret;
                                 76                 : }
                                 77                 : 
                                 78                 : struct connection *
 5667 meskes                     79            3907 : ecpg_get_connection(const char *connection_name)
                                 80                 : {
 7188 bruce                      81            3907 :     struct connection *ret = NULL;
                                 82                 : 
 6964                            83            3907 :     if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
                                 84                 :     {
                                 85                 : #ifdef ENABLE_THREAD_SAFETY
  299 tgl                        86            3499 :         ecpg_pthreads_init();   /* ensure actual_connection_key is valid */
                                 87                 : 
 6964 bruce                      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                 :          */
  299 tgl                        95            3499 :         if (ret == NULL)
                                 96                 :             /* no TSD connection here either, using global */
 6385 bruce                      97              53 :             ret = actual_connection;
                                 98                 : #else
                                 99                 :         ret = actual_connection;
                                100                 : #endif
                                101                 :     }
                                102                 :     else
                                103                 :     {
                                104                 : #ifdef ENABLE_THREAD_SAFETY
 6964                           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                 : 
 2061 peter_e                   115            3907 :     return ret;
                                116                 : }
                                117                 : 
                                118                 : static void
 2118 tgl                       119             122 : ecpg_finish(struct connection *act)
                                120                 : {
 7329 meskes                    121             122 :     if (act != NULL)
                                122                 :     {
                                123                 :         struct ECPGtype_information_cache *cache,
                                124                 :                    *ptr;
                                125                 : 
 5667                           126             122 :         ecpg_deallocate_all_conn(0, ECPG_COMPAT_PGSQL, act);
 7329                           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
 6797 bruce                     147             122 :         if (pthread_getspecific(actual_connection_key) == act)
                                148             122 :             pthread_setspecific(actual_connection_key, all_connections);
                                149                 : #endif
 7329 meskes                    150             122 :         if (actual_connection == act)
                                151              75 :             actual_connection = all_connections;
                                152                 : 
 5226                           153             122 :         ecpg_log("ecpg_finish: connection %s closed\n", act->name ? act->name : "(null)");
                                154                 : 
 5667                           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 */
 4112                           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
 5441 peter_e                   167 UBC           0 :         ecpg_log("ecpg_finish: called an extra time\n");
 7329 meskes                    168 CBC         122 : }
                                169                 : 
                                170                 : bool
                                171              42 : ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
                                172                 : {
 5667                           173              42 :     struct connection *con = ecpg_get_connection(connection_name);
                                174                 :     PGresult   *results;
                                175                 : 
                                176              42 :     if (!ecpg_init(con, connection_name, lineno))
 2061 peter_e                   177 UBC           0 :         return false;
                                178                 : 
 5441 peter_e                   179 CBC          42 :     ecpg_log("ECPGsetcommit on line %d: action \"%s\"; connection \"%s\"\n", lineno, mode, con->name);
                                180                 : 
 4529 rhaas                     181              42 :     if (con->autocommit && strncmp(mode, "off", strlen("off")) == 0)
                                182                 :     {
 4560 meskes                    183 UBC           0 :         if (PQtransactionStatus(con->connection) == PQTRANS_IDLE)
                                184                 :         {
 5717                           185               0 :             results = PQexec(con->connection, "begin transaction");
 5667                           186               0 :             if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL))
 7329                           187               0 :                 return false;
                                188               0 :             PQclear(results);
                                189                 :         }
                                190               0 :         con->autocommit = false;
                                191                 :     }
 4529 rhaas                     192 CBC          42 :     else if (!con->autocommit && strncmp(mode, "on", strlen("on")) == 0)
                                193                 :     {
 4560 meskes                    194              39 :         if (PQtransactionStatus(con->connection) != PQTRANS_IDLE)
                                195                 :         {
 5717 meskes                    196 UBC           0 :             results = PQexec(con->connection, "commit");
 5667                           197               0 :             if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL))
 7329                           198               0 :                 return false;
                                199               0 :             PQclear(results);
                                200                 :         }
 7329 meskes                    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                 : {
 5667                           210               2 :     struct connection *con = ecpg_get_connection(connection_name);
                                211                 : 
                                212               2 :     if (!ecpg_init(con, connection_name, lineno))
 2061 peter_e                   213 UBC           0 :         return false;
                                214                 : 
                                215                 : #ifdef ENABLE_THREAD_SAFETY
 6965 meskes                    216 CBC           2 :     pthread_setspecific(actual_connection_key, con);
                                217                 : #else
                                218                 :     actual_connection = con;
                                219                 : #endif
 7329                           220               2 :     return true;
                                221                 : }
                                222                 : 
                                223                 : 
                                224                 : static void
 7191 peter_e                   225               2 : ECPGnoticeReceiver(void *arg, const PGresult *result)
                                226                 : {
 7168                           227               2 :     char       *sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE);
                                228               2 :     char       *message = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
 7238 bruce                     229               2 :     struct sqlca_t *sqlca = ECPGget_sqlca();
                                230                 :     int         sqlcode;
                                231                 : 
 2855 meskes                    232               2 :     if (sqlca == NULL)
                                233                 :     {
 2855 meskes                    234 UBC           0 :         ecpg_log("out of memory");
                                235               0 :         return;
                                236                 :     }
                                237                 : 
                                238                 :     (void) arg;                 /* keep the compiler quiet */
 7184 peter_e                   239 CBC           2 :     if (sqlstate == NULL)
 7184 peter_e                   240 UBC           0 :         sqlstate = ECPG_SQLSTATE_ECPG_INTERNAL_ERROR;
                                241                 : 
 6031 bruce                     242 CBC           2 :     if (message == NULL)        /* Shouldn't happen, but need to be sure */
 5197 peter_e                   243 UBC           0 :         message = ecpg_gettext("empty message text");
                                244                 : 
                                245                 :     /* these are not warnings */
 7188 bruce                     246 CBC           2 :     if (strncmp(sqlstate, "00", 2) == 0)
 7329 meskes                    247               1 :         return;
                                248                 : 
 5441 peter_e                   249               1 :     ecpg_log("ECPGnoticeReceiver: %s\n", message);
                                250                 : 
                                251                 :     /* map to SQLCODE for backward compatibility */
 7188 bruce                     252               1 :     if (strcmp(sqlstate, ECPG_SQLSTATE_INVALID_CURSOR_NAME) == 0)
 7191 peter_e                   253 UBC           0 :         sqlcode = ECPG_WARNING_UNKNOWN_PORTAL;
 7188 bruce                     254 CBC           1 :     else if (strcmp(sqlstate, ECPG_SQLSTATE_ACTIVE_SQL_TRANSACTION) == 0)
 7191 peter_e                   255 UBC           0 :         sqlcode = ECPG_WARNING_IN_TRANSACTION;
 7188 bruce                     256 CBC           1 :     else if (strcmp(sqlstate, ECPG_SQLSTATE_NO_ACTIVE_SQL_TRANSACTION) == 0)
 7191 peter_e                   257 UBC           0 :         sqlcode = ECPG_WARNING_NO_TRANSACTION;
 7188 bruce                     258 CBC           1 :     else if (strcmp(sqlstate, ECPG_SQLSTATE_DUPLICATE_CURSOR) == 0)
 7191 peter_e                   259 UBC           0 :         sqlcode = ECPG_WARNING_PORTAL_EXISTS;
                                260                 :     else
 7191 peter_e                   261 CBC           1 :         sqlcode = 0;
                                262                 : 
                                263               1 :     strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate));
                                264               1 :     sqlca->sqlcode = sqlcode;
 7238 bruce                     265               1 :     sqlca->sqlwarn[2] = 'W';
                                266               1 :     sqlca->sqlwarn[0] = 'W';
                                267                 : 
 7191 peter_e                   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                 : 
 5667 meskes                    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
 7228                           277             130 : ECPGconnect(int lineno, int c, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
                                278                 : {
 7238 bruce                     279             130 :     struct sqlca_t *sqlca = ECPGget_sqlca();
 7228 meskes                    280             130 :     enum COMPAT_MODE compat = c;
                                281                 :     struct connection *this;
                                282                 :     int         i,
 3955 bruce                     283             130 :                 connect_params = 0;
 5667 meskes                    284             130 :     char       *dbname = name ? ecpg_strdup(name, lineno) : NULL,
 7329                           285             130 :                *host = NULL,
                                286                 :                *tmp,
                                287             130 :                *port = NULL,
                                288             130 :                *realname = NULL,
 4083                           289             130 :                *options = NULL;
                                290                 :     const char **conn_keywords;
                                291                 :     const char **conn_values;
                                292                 : 
 2855                           293             130 :     if (sqlca == NULL)
                                294                 :     {
 2855 meskes                    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                 : 
 5667 meskes                    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                 : 
 7227                           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                 :          */
 7228                           318               6 :         envname = getenv("PG_DBPATH");
                                319               6 :         if (envname)
                                320                 :         {
 5667 meskes                    321 UBC           0 :             ecpg_free(dbname);
                                322               0 :             dbname = ecpg_strdup(envname, lineno);
                                323                 :         }
                                324                 :     }
                                325                 : 
 7329 meskes                    326 CBC         130 :     if (dbname == NULL && connection_name == NULL)
 7329 meskes                    327 UBC           0 :         connection_name = "DEFAULT";
                                328                 : 
                                329                 : #if ENABLE_THREAD_SAFETY
 6094 meskes                    330 CBC         130 :     ecpg_pthreads_init();
                                331                 : #endif
                                332                 : 
                                333                 :     /* check if the identifier is unique */
 5667                           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);
 6099                           339               2 :         return false;
                                340                 :     }
                                341                 : 
 5667                           342             128 :     if ((this = (struct connection *) ecpg_alloc(sizeof(struct connection), lineno)) == NULL)
                                343                 :     {
 2855 meskes                    344 UBC           0 :         ecpg_free(dbname);
 6099                           345               0 :         return false;
                                346                 :     }
                                347                 : 
 6674 meskes                    348 CBC         128 :     if (dbname != NULL)
                                349                 :     {
                                350                 :         /* get the detail information from dbname */
 6069                           351             128 :         if (strncmp(dbname, "tcp:", 4) == 0 || strncmp(dbname, "unix:", 5) == 0)
 6674                           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)
 6674 meskes                    359 UBC           0 :                 offset = 4;
 6674 meskes                    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                 :                 {
 5667                           376               2 :                     options = ecpg_strdup(tmp + 1, lineno);
 6674                           377               2 :                     *tmp = '\0';
                                378                 :                 }
                                379                 : 
                                380               6 :                 tmp = last_dir_separator(dbname + offset);
                                381               6 :                 if (tmp != NULL)    /* database name given */
                                382                 :                 {
 5491                           383               6 :                     if (tmp[1] != '\0') /* non-empty database name */
                                384                 :                     {
                                385               5 :                         realname = ecpg_strdup(tmp + 1, lineno);
 4069                           386               5 :                         connect_params++;
                                387                 :                     }
 6674                           388               6 :                     *tmp = '\0';
                                389                 :                 }
                                390                 : 
                                391               6 :                 tmp = strrchr(dbname + offset, ':');
  787 tgl                       392               6 :                 if (tmp != NULL)    /* port number given */
                                393                 :                 {
 6674 meskes                    394 UBC           0 :                     *tmp = '\0';
  787 tgl                       395               0 :                     port = ecpg_strdup(tmp + 1, lineno);
                                396               0 :                     connect_params++;
                                397                 :                 }
                                398                 : 
 6674 meskes                    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                 :                      */
  787 tgl                       406               6 :                     if (strcmp(dbname + offset, "localhost") != 0 &&
                                407               1 :                         strcmp(dbname + offset, "127.0.0.1") != 0)
                                408                 :                     {
 5441 peter_e                   409               1 :                         ecpg_log("ECPGconnect: non-localhost access via sockets on line %d\n", lineno);
 5197                           410               1 :                         ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : ecpg_gettext("<DEFAULT>"));
 7329 meskes                    411               1 :                         if (host)
 5667 meskes                    412 UBC           0 :                             ecpg_free(host);
 7329 meskes                    413 CBC           1 :                         if (port)
 5667 meskes                    414 UBC           0 :                             ecpg_free(port);
 7329 meskes                    415 CBC           1 :                         if (options)
 5667 meskes                    416 UBC           0 :                             ecpg_free(options);
 7329 meskes                    417 CBC           1 :                         if (realname)
 5667                           418               1 :                             ecpg_free(realname);
 7329                           419               1 :                         if (dbname)
 5667                           420               1 :                             ecpg_free(dbname);
 6069                           421               1 :                         free(this);
 7329                           422               1 :                         return false;
                                423                 :                     }
                                424                 :                 }
                                425                 :                 else
                                426                 :                 {
 3385 meskes                    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] */
 6069 meskes                    438 CBC         122 :             tmp = strrchr(dbname, ':');
                                439             122 :             if (tmp != NULL)    /* port number given */
                                440                 :             {
 5667 meskes                    441 UBC           0 :                 port = ecpg_strdup(tmp + 1, lineno);
 4069                           442               0 :                 connect_params++;
 6069                           443               0 :                 *tmp = '\0';
                                444                 :             }
                                445                 : 
 6069 meskes                    446 CBC         122 :             tmp = strrchr(dbname, '@');
                                447             122 :             if (tmp != NULL)    /* host name given */
                                448                 :             {
 5667 meskes                    449 UBC           0 :                 host = ecpg_strdup(tmp + 1, lineno);
 4069                           450               0 :                 connect_params++;
 6069                           451               0 :                 *tmp = '\0';
                                452                 :             }
                                453                 : 
 4069 meskes                    454 CBC         122 :             if (strlen(dbname) > 0)
                                455                 :             {
                                456             122 :                 realname = ecpg_strdup(dbname, lineno);
                                457             122 :                 connect_params++;
                                458                 :             }
                                459                 :             else
 4069 meskes                    460 UBC           0 :                 realname = NULL;
                                461                 :         }
                                462                 :     }
                                463                 :     else
 6674                           464               0 :         realname = NULL;
                                465                 : 
                                466                 :     /*
                                467                 :      * Count options for the allocation done below (this may produce an
                                468                 :      * overestimate, it's ok).
                                469                 :      */
 4069 meskes                    470 CBC         127 :     if (options)
 5491                           471              67 :         for (i = 0; options[i]; i++)
 4069                           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                 :      */
 3955 bruce                     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);
 4069 meskes                    487             127 :     if (conn_keywords == NULL || conn_values == NULL)
                                488                 :     {
 4069 meskes                    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);
 4049 peter_e                   499               0 :         if (conn_keywords)
                                500               0 :             ecpg_free(conn_keywords);
                                501               0 :         if (conn_values)
                                502               0 :             ecpg_free(conn_values);
 4069 meskes                    503               0 :         free(this);
                                504               0 :         return false;
                                505                 :     }
                                506                 : 
                                507                 :     /* add connection to our list */
                                508                 : #ifdef ENABLE_THREAD_SAFETY
  573 michael                   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
  281 noah                      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
  281 noah                      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                 : 
  573 michael                   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>",
  573 michael                   569 UBC           0 :              port ? (ecpg_internal_regression_mode ? "<REGRESSION_PORT>" : port) : "<DEFAULT>",
                                570                 :              options ? "with options " : "", options ? options : "",
  573 michael                   571 CBC           6 :              (user && strlen(user) > 0) ? "for user " : "", user ? user : "");
                                572                 : 
 4083 meskes                    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                 :     {
 4083 meskes                    582 UBC           0 :         conn_keywords[i] = "host";
                                583               0 :         conn_values[i] = host;
                                584               0 :         i++;
                                585                 :     }
 4083 meskes                    586 CBC         127 :     if (port)
                                587                 :     {
 4083 meskes                    588 UBC           0 :         conn_keywords[i] = "port";
                                589               0 :         conn_values[i] = port;
                                590               0 :         i++;
                                591                 :     }
 4083 meskes                    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                 :          */
 4067                           614               5 :         for (str = options; *str;)
                                615                 :         {
                                616                 :             int         e,
                                617                 :                         a;
                                618                 :             char       *token1,
                                619                 :                        *token2;
                                620                 : 
                                621                 :             /* Skip spaces before keyword */
 1317 tgl                       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 */ ;
 3955 bruce                     627               3 :             if (token1[e])      /* found "=" */
                                628                 :             {
 4067 meskes                    629               3 :                 token1[e] = '\0';
                                630                 :                 /* Skip spaces before value */
 1317 tgl                       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 */ ;
 3955 bruce                     636               3 :                 if (token2[a])  /* found "&" => another option follows */
                                637                 :                 {
 4067 meskes                    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 */
 3955 bruce                     651 UBC           0 :                 str = token1 + e;
                                652                 :             }
                                653                 :         }
                                654                 :     }
                                655                 : 
 1317 tgl                       656 CBC         127 :     Assert(i <= connect_params);
 4083 meskes                    657             127 :     conn_keywords[i] = NULL;    /* terminator */
                                658                 : 
                                659             127 :     this->connection = PQconnectdbParams(conn_keywords, conn_values, 0);
                                660                 : 
 5491                           661             127 :     if (host)
 5491 meskes                    662 UBC           0 :         ecpg_free(host);
 5491 meskes                    663 CBC         127 :     if (port)
 5491 meskes                    664 UBC           0 :         ecpg_free(port);
 5491 meskes                    665 CBC         127 :     if (options)
                                666               2 :         ecpg_free(options);
                                667             127 :     if (dbname)
                                668             127 :         ecpg_free(dbname);
 4069                           669             127 :     ecpg_free(conn_values);
                                670             127 :     ecpg_free(conn_keywords);
                                671                 : 
 7329                           672             127 :     if (PQstatus(this->connection) == CONNECTION_BAD)
                                673                 :     {
 7188 bruce                     674               1 :         const char *errmsg = PQerrorMessage(this->connection);
 5197 peter_e                   675               1 :         const char *db = realname ? realname : ecpg_gettext("<DEFAULT>");
                                676                 : 
                                677                 :         /* PQerrorMessage's result already has a trailing newline */
  807 tgl                       678               1 :         ecpg_log("ECPGconnect: %s", errmsg);
                                679                 : 
 6138 meskes                    680               1 :         ecpg_finish(this);
                                681                 : #ifdef ENABLE_THREAD_SAFETY
                                682               1 :         pthread_mutex_unlock(&connections_mutex);
                                683                 : #endif
                                684                 : 
 5667                           685               1 :         ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, db);
 7329                           686               1 :         if (realname)
 5667 meskes                    687 UBC           0 :             ecpg_free(realname);
                                688                 : 
 7329 meskes                    689 CBC           1 :         return false;
                                690                 :     }
                                691                 : 
                                692             126 :     if (realname)
 5667                           693             126 :         ecpg_free(realname);
                                694                 : 
                                695                 : #ifdef ENABLE_THREAD_SAFETY
 5491                           696             126 :     pthread_mutex_unlock(&connections_mutex);
                                697                 : #endif
                                698                 : 
 7329                           699             126 :     this->autocommit = autocommit;
                                700                 : 
 7191 peter_e                   701             126 :     PQsetNoticeReceiver(this->connection, &ECPGnoticeReceiver, (void *) this);
                                702                 : 
 7329 meskes                    703             126 :     return true;
                                704                 : }
                                705                 : 
                                706                 : bool
                                707             127 : ECPGdisconnect(int lineno, const char *connection_name)
                                708                 : {
 7238 bruce                     709             127 :     struct sqlca_t *sqlca = ECPGget_sqlca();
                                710                 :     struct connection *con;
                                711                 : 
 2855 meskes                    712             127 :     if (sqlca == NULL)
                                713                 :     {
 2855 meskes                    714 UBC           0 :         ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
                                715                 :                    ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
 2061 peter_e                   716               0 :         return false;
                                717                 :     }
                                718                 : 
                                719                 : #ifdef ENABLE_THREAD_SAFETY
 7238 bruce                     720 CBC         127 :     pthread_mutex_lock(&connections_mutex);
                                721                 : #endif
                                722                 : 
 7329 meskes                    723             127 :     if (strcmp(connection_name, "ALL") == 0)
                                724                 :     {
 5667                           725              16 :         ecpg_init_sqlca(sqlca);
 7329                           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                 :     {
 7222                           736             111 :         con = ecpg_get_connection_nr(connection_name);
                                737                 : 
 5667                           738             111 :         if (!ecpg_init(con, connection_name, lineno))
                                739                 :         {
                                740                 : #ifdef ENABLE_THREAD_SAFETY
 7188 bruce                     741               8 :             pthread_mutex_unlock(&connections_mutex);
                                742                 : #endif
 2061 peter_e                   743               8 :             return false;
                                744                 :         }
                                745                 :         else
 7188 bruce                     746             103 :             ecpg_finish(con);
                                747                 :     }
                                748                 : 
                                749                 : #ifdef ENABLE_THREAD_SAFETY
 7238                           750             119 :     pthread_mutex_unlock(&connections_mutex);
                                751                 : #endif
                                752                 : 
 7329 meskes                    753             119 :     return true;
                                754                 : }
                                755                 : 
                                756                 : PGconn *
 5050 bruce                     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                 : 
 5498 meskes                    765               0 :     return con->connection;
                                766                 : }
        

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