LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - connect.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 269 345 78.0 %
Date: 2019-06-19 16:07:09 Functions: 10 11 90.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13