LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - connect.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 424 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 11 0
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.3.2-1