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