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