NLS cleanup in ecpglib
[PostgreSQL.git] / src / interfaces / ecpg / ecpglib / connect.c
blob664388a21424cc02be171e5ba022a4ce606338ac
1 /* $PostgreSQL$ */
3 #define POSTGRES_ECPG_INTERNAL
4 #include "postgres_fe.h"
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"
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;
21 #ifdef ENABLE_THREAD_SAFETY
22 static void
23 ecpg_actual_connection_init(void)
25 pthread_key_create(&actual_connection_key, NULL);
28 void
29 ecpg_pthreads_init(void)
31 pthread_once(&actual_connection_key_once, ecpg_actual_connection_init);
33 #endif
35 static struct connection *
36 ecpg_get_connection_nr(const char *connection_name)
38 struct connection *ret = NULL;
40 if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
42 #ifdef ENABLE_THREAD_SAFETY
43 ret = pthread_getspecific(actual_connection_key);
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
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
58 else
60 struct connection *con;
62 for (con = all_connections; con != NULL; con = con->next)
64 if (strcmp(connection_name, con->name) == 0)
65 break;
67 ret = con;
70 return (ret);
73 struct connection *
74 ecpg_get_connection(const char *connection_name)
76 struct connection *ret = NULL;
78 if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
80 #ifdef ENABLE_THREAD_SAFETY
81 ret = pthread_getspecific(actual_connection_key);
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
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
96 else
98 #ifdef ENABLE_THREAD_SAFETY
99 pthread_mutex_lock(&connections_mutex);
100 #endif
102 ret = ecpg_get_connection_nr(connection_name);
104 #ifdef ENABLE_THREAD_SAFETY
105 pthread_mutex_unlock(&connections_mutex);
106 #endif
109 return (ret);
112 static void
113 ecpg_finish(struct connection * act)
115 if (act != NULL)
117 struct ECPGtype_information_cache *cache,
118 *ptr;
120 ecpg_deallocate_all_conn(0, ECPG_COMPAT_PGSQL, act);
121 PQfinish(act->connection);
124 * no need to lock connections_mutex - we're always called by
125 * ECPGdisconnect or ECPGconnect, which are holding the lock
128 /* remove act from the list */
129 if (act == all_connections)
130 all_connections = act->next;
131 else
133 struct connection *con;
135 for (con = all_connections; con->next && con->next != act; con = con->next);
136 if (con->next)
137 con->next = act->next;
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;
147 ecpg_log("ecpg_finish: connection %s closed\n", act->name ? act->name : "(null)");
149 for (cache = act->cache_head; cache; ptr = cache, cache = cache->next, ecpg_free(ptr));
150 ecpg_free(act->name);
151 ecpg_free(act);
153 else
154 ecpg_log("ecpg_finish: called an extra time\n");
157 bool
158 ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
160 struct connection *con = ecpg_get_connection(connection_name);
161 PGresult *results;
163 if (!ecpg_init(con, connection_name, lineno))
164 return (false);
166 ecpg_log("ECPGsetcommit on line %d: action \"%s\"; connection \"%s\"\n", lineno, mode, con->name);
168 if (con->autocommit == true && strncmp(mode, "off", strlen("off")) == 0)
170 if (con->committed)
172 results = PQexec(con->connection, "begin transaction");
173 if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL))
174 return false;
175 PQclear(results);
176 con->committed = false;
178 con->autocommit = false;
180 else if (con->autocommit == false && strncmp(mode, "on", strlen("on")) == 0)
182 if (!con->committed)
184 results = PQexec(con->connection, "commit");
185 if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL))
186 return false;
187 PQclear(results);
188 con->committed = true;
190 con->autocommit = true;
193 return true;
196 bool
197 ECPGsetconn(int lineno, const char *connection_name)
199 struct connection *con = ecpg_get_connection(connection_name);
201 if (!ecpg_init(con, connection_name, lineno))
202 return (false);
204 #ifdef ENABLE_THREAD_SAFETY
205 pthread_setspecific(actual_connection_key, con);
206 #else
207 actual_connection = con;
208 #endif
209 return true;
213 static void
214 ECPGnoticeReceiver(void *arg, const PGresult *result)
216 char *sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE);
217 char *message = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
218 struct sqlca_t *sqlca = ECPGget_sqlca();
220 int sqlcode;
222 if (sqlstate == NULL)
223 sqlstate = ECPG_SQLSTATE_ECPG_INTERNAL_ERROR;
225 if (message == NULL) /* Shouldn't happen, but need to be sure */
226 message = ecpg_gettext("empty message text");
228 /* these are not warnings */
229 if (strncmp(sqlstate, "00", 2) == 0)
230 return;
232 ecpg_log("ECPGnoticeReceiver: %s\n", message);
234 /* map to SQLCODE for backward compatibility */
235 if (strcmp(sqlstate, ECPG_SQLSTATE_INVALID_CURSOR_NAME) == 0)
236 sqlcode = ECPG_WARNING_UNKNOWN_PORTAL;
237 else if (strcmp(sqlstate, ECPG_SQLSTATE_ACTIVE_SQL_TRANSACTION) == 0)
238 sqlcode = ECPG_WARNING_IN_TRANSACTION;
239 else if (strcmp(sqlstate, ECPG_SQLSTATE_NO_ACTIVE_SQL_TRANSACTION) == 0)
240 sqlcode = ECPG_WARNING_NO_TRANSACTION;
241 else if (strcmp(sqlstate, ECPG_SQLSTATE_DUPLICATE_CURSOR) == 0)
242 sqlcode = ECPG_WARNING_PORTAL_EXISTS;
243 else
244 sqlcode = 0;
246 strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate));
247 sqlca->sqlcode = sqlcode;
248 sqlca->sqlwarn[2] = 'W';
249 sqlca->sqlwarn[0] = 'W';
251 strncpy(sqlca->sqlerrm.sqlerrmc, message, sizeof(sqlca->sqlerrm.sqlerrmc));
252 sqlca->sqlerrm.sqlerrmc[sizeof(sqlca->sqlerrm.sqlerrmc) - 1] = 0;
253 sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
255 ecpg_log("raising sqlcode %d\n", sqlcode);
258 static int
259 strlen_or_null(const char *string)
261 if (!string)
262 return 0;
263 return (strlen(string));
266 /* this contains some quick hacks, needs to be cleaned up, but it works */
267 bool
268 ECPGconnect(int lineno, int c, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
270 struct sqlca_t *sqlca = ECPGget_sqlca();
271 enum COMPAT_MODE compat = c;
272 struct connection *this;
273 int i;
274 char *dbname = name ? ecpg_strdup(name, lineno) : NULL,
275 *host = NULL,
276 *tmp,
277 *port = NULL,
278 *realname = NULL,
279 *options = NULL,
280 *connect_string = NULL;
282 ecpg_init_sqlca(sqlca);
285 * clear auto_mem structure because some error handling functions might
286 * access it
288 ecpg_clear_auto_mem();
290 if (INFORMIX_MODE(compat))
292 char *envname;
295 * Informix uses an environment variable DBPATH that overrides the
296 * connection parameters given here. We do the same with PG_DBPATH as
297 * the syntax is different.
299 envname = getenv("PG_DBPATH");
300 if (envname)
302 ecpg_free(dbname);
303 dbname = ecpg_strdup(envname, lineno);
308 if (dbname == NULL && connection_name == NULL)
309 connection_name = "DEFAULT";
311 #if ENABLE_THREAD_SAFETY
312 ecpg_pthreads_init();
313 #endif
315 /* check if the identifier is unique */
316 if (ecpg_get_connection(connection_name))
318 ecpg_free(dbname);
319 ecpg_log("ECPGconnect: connection identifier %s is already in use\n",
320 connection_name);
321 return false;
324 if ((this = (struct connection *) ecpg_alloc(sizeof(struct connection), lineno)) == NULL)
325 return false;
327 if (dbname != NULL)
329 /* get the detail information out of dbname */
330 if (strncmp(dbname, "tcp:", 4) == 0 || strncmp(dbname, "unix:", 5) == 0)
332 int offset = 0;
335 * only allow protocols tcp and unix
337 if (strncmp(dbname, "tcp:", 4) == 0)
338 offset = 4;
339 else if (strncmp(dbname, "unix:", 5) == 0)
340 offset = 5;
342 if (strncmp(dbname + offset, "postgresql://", strlen("postgresql://")) == 0)
345 /*------
346 * new style:
347 * <tcp|unix>:postgresql://server[:port|:/unixsocket/path:]
348 * [/db name][?options]
349 *------
351 offset += strlen("postgresql://");
353 tmp = strrchr(dbname + offset, '?');
354 if (tmp != NULL) /* options given */
356 options = ecpg_strdup(tmp + 1, lineno);
357 *tmp = '\0';
360 tmp = last_dir_separator(dbname + offset);
361 if (tmp != NULL) /* database name given */
363 if (tmp[1] != '\0') /* non-empty database name */
364 realname = ecpg_strdup(tmp + 1, lineno);
365 *tmp = '\0';
368 tmp = strrchr(dbname + offset, ':');
369 if (tmp != NULL) /* port number or Unix socket path given */
371 char *tmp2;
373 *tmp = '\0';
374 if ((tmp2 = strchr(tmp + 1, ':')) != NULL)
376 *tmp2 = '\0';
377 host = ecpg_strdup(tmp + 1, lineno);
378 if (strncmp(dbname, "unix:", 5) != 0)
380 ecpg_log("ECPGconnect: socketname %s given for TCP connection on line %d\n", host, lineno);
381 ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : ecpg_gettext("<DEFAULT>"));
382 if (host)
383 ecpg_free(host);
386 * port not set yet if (port) ecpg_free(port);
388 if (options)
389 ecpg_free(options);
390 if (realname)
391 ecpg_free(realname);
392 if (dbname)
393 ecpg_free(dbname);
394 free(this);
395 return false;
398 else
399 port = ecpg_strdup(tmp + 1, lineno);
402 if (strncmp(dbname, "unix:", 5) == 0)
404 if (strcmp(dbname + offset, "localhost") != 0 && strcmp(dbname + offset, "127.0.0.1") != 0)
406 ecpg_log("ECPGconnect: non-localhost access via sockets on line %d\n", lineno);
407 ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : ecpg_gettext("<DEFAULT>"));
408 if (host)
409 ecpg_free(host);
410 if (port)
411 ecpg_free(port);
412 if (options)
413 ecpg_free(options);
414 if (realname)
415 ecpg_free(realname);
416 if (dbname)
417 ecpg_free(dbname);
418 free(this);
419 return false;
422 else
423 host = ecpg_strdup(dbname + offset, lineno);
427 else
429 /* old style: dbname[@server][:port] */
430 tmp = strrchr(dbname, ':');
431 if (tmp != NULL) /* port number given */
433 port = ecpg_strdup(tmp + 1, lineno);
434 *tmp = '\0';
437 tmp = strrchr(dbname, '@');
438 if (tmp != NULL) /* host name given */
440 host = ecpg_strdup(tmp + 1, lineno);
441 *tmp = '\0';
444 realname = (strlen(dbname) > 0) ? ecpg_strdup(dbname, lineno) : NULL;
447 else
448 realname = NULL;
450 /* add connection to our list */
451 #ifdef ENABLE_THREAD_SAFETY
452 pthread_mutex_lock(&connections_mutex);
453 #endif
454 if (connection_name != NULL)
455 this->name = ecpg_strdup(connection_name, lineno);
456 else
457 this->name = ecpg_strdup(realname, lineno);
459 this->cache_head = NULL;
460 this->prep_stmts = NULL;
462 if (all_connections == NULL)
463 this->next = NULL;
464 else
465 this->next = all_connections;
467 all_connections = this;
468 #ifdef ENABLE_THREAD_SAFETY
469 pthread_setspecific(actual_connection_key, all_connections);
470 #endif
471 actual_connection = all_connections;
473 ecpg_log("ECPGconnect: opening database %s on %s port %s %s%s %s%s\n",
474 realname ? realname : "<DEFAULT>",
475 host ? host : "<DEFAULT>",
476 port ? (ecpg_internal_regression_mode ? "<REGRESSION_PORT>" : port) : "<DEFAULT>",
477 options ? "with options " : "", options ? options : "",
478 user ? "for user " : "", user ? user : "");
480 connect_string = ecpg_alloc( strlen_or_null(host)
481 + strlen_or_null(port)
482 + strlen_or_null(options)
483 + strlen_or_null(realname)
484 + strlen_or_null(user)
485 + strlen_or_null(passwd)
486 + sizeof(" host = port = dbname = user = password ="), lineno);
488 if (options) /* replace '&' if tehre are any */
489 for (i = 0; options[i]; i++)
490 if (options[i] == '&')
491 options[i] = ' ';
493 sprintf(connect_string,"%s%s %s%s %s%s %s%s %s%s %s",
494 realname ? "dbname=" : "", realname ? realname : "",
495 host ? "host=" : "", host ? host : "",
496 port ? "port=" : "", port ? port : "",
497 user ? "user=" : "", user ? user : "",
498 passwd ? "password=" : "", passwd ? passwd : "",
499 options ? options : "");
501 /* this is deprecated
502 * this->connection = PQsetdbLogin(host, port, options, NULL, realname, user, passwd);*/
503 this->connection = PQconnectdb(connect_string);
505 ecpg_free(connect_string);
506 if (host)
507 ecpg_free(host);
508 if (port)
509 ecpg_free(port);
510 if (options)
511 ecpg_free(options);
512 if (dbname)
513 ecpg_free(dbname);
515 if (PQstatus(this->connection) == CONNECTION_BAD)
517 const char *errmsg = PQerrorMessage(this->connection);
518 const char *db = realname ? realname : ecpg_gettext("<DEFAULT>");
520 ecpg_log("ECPGconnect: could not open database: %s\n", errmsg);
522 ecpg_finish(this);
523 #ifdef ENABLE_THREAD_SAFETY
524 pthread_mutex_unlock(&connections_mutex);
525 #endif
527 ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, db);
528 if (realname)
529 ecpg_free(realname);
531 return false;
534 if (realname)
535 ecpg_free(realname);
537 #ifdef ENABLE_THREAD_SAFETY
538 pthread_mutex_unlock(&connections_mutex);
539 #endif
541 this->committed = true;
542 this->autocommit = autocommit;
544 PQsetNoticeReceiver(this->connection, &ECPGnoticeReceiver, (void *) this);
546 return true;
549 bool
550 ECPGdisconnect(int lineno, const char *connection_name)
552 struct sqlca_t *sqlca = ECPGget_sqlca();
553 struct connection *con;
555 #ifdef ENABLE_THREAD_SAFETY
556 pthread_mutex_lock(&connections_mutex);
557 #endif
559 if (strcmp(connection_name, "ALL") == 0)
561 ecpg_init_sqlca(sqlca);
562 for (con = all_connections; con;)
564 struct connection *f = con;
566 con = con->next;
567 ecpg_finish(f);
570 else
572 con = ecpg_get_connection_nr(connection_name);
574 if (!ecpg_init(con, connection_name, lineno))
576 #ifdef ENABLE_THREAD_SAFETY
577 pthread_mutex_unlock(&connections_mutex);
578 #endif
579 return (false);
581 else
582 ecpg_finish(con);
585 #ifdef ENABLE_THREAD_SAFETY
586 pthread_mutex_unlock(&connections_mutex);
587 #endif
589 return true;
592 PGconn* ECPGget_PGconn(const char *connection_name)
594 struct connection * con;
596 con=ecpg_get_connection(connection_name);
597 if (con==NULL) return NULL;
599 return con->connection;