Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

PostgreSQL Source Code git master
connect.c
Go to the documentation of this file.
1/* src/interfaces/ecpg/ecpglib/connect.c */
2
3#define POSTGRES_ECPG_INTERNAL
4#include "postgres_fe.h"
5
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
14locale_t ecpg_clocale = (locale_t) 0;
15#endif
16
19static pthread_once_t actual_connection_key_once = PTHREAD_ONCE_INIT;
20static struct connection *actual_connection = NULL;
21static struct connection *all_connections = NULL;
22
23static void
25{
26 pthread_key_create(&actual_connection_key, NULL);
27}
28
29void
31{
33}
34
35static struct connection *
36ecpg_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 ecpg_pthreads_init(); /* ensure actual_connection_key is valid */
43
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 if (ret == NULL)
52 /* no TSD connection, going for global */
54 }
55 else
56 {
57 struct connection *con;
58
59 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 if (con->name != NULL && strcmp(connection_name, con->name) == 0)
67 break;
68 }
69 ret = con;
70 }
71
72 return ret;
73}
74
75struct connection *
76ecpg_get_connection(const char *connection_name)
77{
78 struct connection *ret = NULL;
79
80 if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
81 {
82 ecpg_pthreads_init(); /* ensure actual_connection_key is valid */
83
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 if (ret == NULL)
92 /* no TSD connection here either, using global */
94 }
95 else
96 {
98
99 ret = ecpg_get_connection_nr(connection_name);
100
102 }
103
104 return ret;
105}
106
107static void
109{
110 if (act != NULL)
111 {
112 struct ECPGtype_information_cache *cache,
113 *ptr;
114
116 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 if (act == all_connections)
125 all_connections = act->next;
126 else
127 {
128 struct connection *con;
129
130 for (con = all_connections; con->next && con->next != act; con = con->next);
131 if (con->next)
132 con->next = act->next;
133 }
134
137 if (actual_connection == act)
139
140 ecpg_log("ecpg_finish: connection %s closed\n", act->name ? act->name : "(null)");
141
142 for (cache = act->cache_head; cache; ptr = cache, cache = cache->next, ecpg_free(ptr));
143 ecpg_free(act->name);
144 ecpg_free(act);
145 /* delete cursor variables when last connection gets closed */
146 if (all_connections == NULL)
147 {
148 struct var_list *iv_ptr;
149
150 for (; ivlist; iv_ptr = ivlist, ivlist = ivlist->next, ecpg_free(iv_ptr));
151 }
152 }
153 else
154 ecpg_log("ecpg_finish: called an extra time\n");
155}
156
157bool
158ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
159{
160 struct connection *con = ecpg_get_connection(connection_name);
161 PGresult *results;
162
163 if (!ecpg_init(con, connection_name, lineno))
164 return false;
165
166 ecpg_log("ECPGsetcommit on line %d: action \"%s\"; connection \"%s\"\n", lineno, mode, con->name);
167
168 if (con->autocommit && strncmp(mode, "off", strlen("off")) == 0)
169 {
171 {
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 }
177 con->autocommit = false;
178 }
179 else if (!con->autocommit && strncmp(mode, "on", strlen("on")) == 0)
180 {
182 {
183 results = PQexec(con->connection, "commit");
184 if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL))
185 return false;
186 PQclear(results);
187 }
188 con->autocommit = true;
189 }
190
191 return true;
192}
193
194bool
195ECPGsetconn(int lineno, const char *connection_name)
196{
197 struct connection *con = ecpg_get_connection(connection_name);
198
199 if (!ecpg_init(con, connection_name, lineno))
200 return false;
201
203 return true;
204}
205
206
207static void
208ECPGnoticeReceiver(void *arg, const PGresult *result)
209{
210 char *sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE);
211 char *message = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
212 struct sqlca_t *sqlca = ECPGget_sqlca();
213 int sqlcode;
214
215 if (sqlca == NULL)
216 {
217 ecpg_log("out of memory");
218 return;
219 }
220
221 (void) arg; /* keep the compiler quiet */
222 if (sqlstate == NULL)
224
225 if (message == NULL) /* Shouldn't happen, but need to be sure */
226 message = ecpg_gettext("empty message text");
227
228 /* these are not warnings */
229 if (strncmp(sqlstate, "00", 2) == 0)
230 return;
231
232 ecpg_log("ECPGnoticeReceiver: %s\n", message);
233
234 /* map to SQLCODE for backward compatibility */
237 else if (strcmp(sqlstate, ECPG_SQLSTATE_ACTIVE_SQL_TRANSACTION) == 0)
241 else if (strcmp(sqlstate, ECPG_SQLSTATE_DUPLICATE_CURSOR) == 0)
243 else
244 sqlcode = 0;
245
246 strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate));
247 sqlca->sqlcode = sqlcode;
248 sqlca->sqlwarn[2] = 'W';
249 sqlca->sqlwarn[0] = 'W';
250
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);
254
255 ecpg_log("raising sqlcode %d\n", sqlcode);
256}
257
258/* this contains some quick hacks, needs to be cleaned up, but it works */
259bool
260ECPGconnect(int lineno, int c, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
261{
262 struct sqlca_t *sqlca = ECPGget_sqlca();
263 enum COMPAT_MODE compat = c;
264 struct connection *this;
265 int i,
266 connect_params = 0;
267 bool alloc_failed = (sqlca == NULL);
268 char *dbname = name ? ecpg_strdup(name, lineno, &alloc_failed) : NULL,
269 *host = NULL,
270 *tmp,
271 *port = NULL,
272 *realname = NULL,
273 *options = NULL;
274 const char **conn_keywords;
275 const char **conn_values;
276
277 if (alloc_failed)
278 {
281 if (dbname)
283 return false;
284 }
285
287
288 /*
289 * clear auto_mem structure because some error handling functions might
290 * access it
291 */
293
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 envname = getenv("PG_DBPATH");
304 if (envname)
305 {
307 dbname = ecpg_strdup(envname, lineno, &alloc_failed);
308 }
309 }
310
311 if (dbname == NULL && connection_name == NULL)
312 connection_name = "DEFAULT";
313
315
316 /* check if the identifier is unique */
317 if (ecpg_get_connection(connection_name))
318 {
320 ecpg_log("ECPGconnect: connection identifier %s is already in use\n",
321 connection_name);
322 return false;
323 }
324
325 if ((this = (struct connection *) ecpg_alloc(sizeof(struct connection), lineno)) == NULL)
326 {
328 return false;
329 }
330
331 if (dbname != NULL)
332 {
333 /* get the detail information from dbname */
334 if (strncmp(dbname, "tcp:", 4) == 0 || strncmp(dbname, "unix:", 5) == 0)
335 {
336 int offset = 0;
337
338 /*
339 * only allow protocols tcp and unix
340 */
341 if (strncmp(dbname, "tcp:", 4) == 0)
342 offset = 4;
343 else if (strncmp(dbname, "unix:", 5) == 0)
344 offset = 5;
345
346 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 offset += strlen("postgresql://");
355
356 tmp = strrchr(dbname + offset, '?');
357 if (tmp != NULL) /* options given */
358 {
359 options = ecpg_strdup(tmp + 1, lineno, &alloc_failed);
360 *tmp = '\0';
361 }
362
363 tmp = last_dir_separator(dbname + offset);
364 if (tmp != NULL) /* database name given */
365 {
366 if (tmp[1] != '\0') /* non-empty database name */
367 {
368 realname = ecpg_strdup(tmp + 1, lineno, &alloc_failed);
369 connect_params++;
370 }
371 *tmp = '\0';
372 }
373
374 tmp = strrchr(dbname + offset, ':');
375 if (tmp != NULL) /* port number given */
376 {
377 *tmp = '\0';
378 port = ecpg_strdup(tmp + 1, lineno, &alloc_failed);
379 connect_params++;
380 }
381
382 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 if (strcmp(dbname + offset, "localhost") != 0 &&
390 strcmp(dbname + offset, "127.0.0.1") != 0)
391 {
392 ecpg_log("ECPGconnect: non-localhost access via sockets on line %d\n", lineno);
394 if (host)
395 ecpg_free(host);
396 if (port)
398 if (options)
400 if (realname)
401 ecpg_free(realname);
402 if (dbname)
404 free(this);
405 return false;
406 }
407 }
408 else
409 {
410 if (*(dbname + offset) != '\0')
411 {
412 host = ecpg_strdup(dbname + offset, lineno, &alloc_failed);
413 connect_params++;
414 }
415 }
416 }
417 }
418 else
419 {
420 /* old style: dbname[@server][:port] */
421 tmp = strrchr(dbname, ':');
422 if (tmp != NULL) /* port number given */
423 {
424 port = ecpg_strdup(tmp + 1, lineno, &alloc_failed);
425 connect_params++;
426 *tmp = '\0';
427 }
428
429 tmp = strrchr(dbname, '@');
430 if (tmp != NULL) /* host name given */
431 {
432 host = ecpg_strdup(tmp + 1, lineno, &alloc_failed);
433 connect_params++;
434 *tmp = '\0';
435 }
436
437 if (strlen(dbname) > 0)
438 {
439 realname = ecpg_strdup(dbname, lineno, &alloc_failed);
440 connect_params++;
441 }
442 else
443 realname = NULL;
444 }
445 }
446 else
447 realname = NULL;
448
449 /*
450 * Count options for the allocation done below (this may produce an
451 * overestimate, it's ok).
452 */
453 if (options)
454 for (i = 0; options[i]; i++)
455 if (options[i] == '=')
456 connect_params++;
457
458 if (user && strlen(user) > 0)
459 connect_params++;
460 if (passwd && strlen(passwd) > 0)
461 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 conn_keywords = (const char **) ecpg_alloc((connect_params + 1) * sizeof(char *), lineno);
469 conn_values = (const char **) ecpg_alloc(connect_params * sizeof(char *), lineno);
470
471 /* Decide on a connection name */
472 if (connection_name != NULL || realname != NULL)
473 {
474 this->name = ecpg_strdup(connection_name ? connection_name : realname,
475 lineno, &alloc_failed);
476 }
477 else
478 this->name = NULL;
479
480 /* Deal with any failed allocations above */
481 if (conn_keywords == NULL || conn_values == NULL || alloc_failed)
482 {
483 if (host)
484 ecpg_free(host);
485 if (port)
487 if (options)
489 if (realname)
490 ecpg_free(realname);
491 if (dbname)
493 if (conn_keywords)
494 ecpg_free(conn_keywords);
495 if (conn_values)
496 ecpg_free(conn_values);
497 if (this->name)
498 ecpg_free(this->name);
499 free(this);
500 return false;
501 }
502
503 /* add connection to our list */
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 if (!ecpg_clocale)
512 {
513 ecpg_clocale = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
514 if (!ecpg_clocale)
515 {
519 if (host)
520 ecpg_free(host);
521 if (port)
523 if (options)
525 if (realname)
526 ecpg_free(realname);
527 if (dbname)
529 if (conn_keywords)
530 ecpg_free(conn_keywords);
531 if (conn_values)
532 ecpg_free(conn_values);
533 if (this->name)
534 ecpg_free(this->name);
535 free(this);
536 return false;
537 }
538 }
539#endif
540
541 this->cache_head = NULL;
542 this->prep_stmts = NULL;
543
544 if (all_connections == NULL)
545 this->next = NULL;
546 else
547 this->next = all_connections;
548
549 all_connections = this;
552
553 ecpg_log("ECPGconnect: opening database %s on %s port %s %s%s %s%s\n",
554 realname ? realname : "<DEFAULT>",
555 host ? host : "<DEFAULT>",
556 port ? (ecpg_internal_regression_mode ? "<REGRESSION_PORT>" : port) : "<DEFAULT>",
557 options ? "with options " : "", options ? options : "",
558 (user && strlen(user) > 0) ? "for user " : "", user ? user : "");
559
560 i = 0;
561 if (realname)
562 {
563 conn_keywords[i] = "dbname";
564 conn_values[i] = realname;
565 i++;
566 }
567 if (host)
568 {
569 conn_keywords[i] = "host";
570 conn_values[i] = host;
571 i++;
572 }
573 if (port)
574 {
575 conn_keywords[i] = "port";
576 conn_values[i] = port;
577 i++;
578 }
579 if (user && strlen(user) > 0)
580 {
581 conn_keywords[i] = "user";
582 conn_values[i] = user;
583 i++;
584 }
585 if (passwd && strlen(passwd) > 0)
586 {
587 conn_keywords[i] = "password";
588 conn_values[i] = passwd;
589 i++;
590 }
591 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 for (str = options; *str;)
605 {
606 int e,
607 a;
608 char *token1,
609 *token2;
610
611 /* Skip spaces before keyword */
612 for (token1 = str; *token1 == ' '; token1++)
613 /* skip */ ;
614 /* Find end of keyword */
615 for (e = 0; token1[e] && token1[e] != '='; e++)
616 /* skip */ ;
617 if (token1[e]) /* found "=" */
618 {
619 token1[e] = '\0';
620 /* Skip spaces before value */
621 for (token2 = token1 + e + 1; *token2 == ' '; token2++)
622 /* skip */ ;
623 /* Find end of value */
624 for (a = 0; token2[a] && token2[a] != '&'; a++)
625 /* skip */ ;
626 if (token2[a]) /* found "&" => another option follows */
627 {
628 token2[a] = '\0';
629 str = token2 + a + 1;
630 }
631 else
632 str = token2 + a;
633
634 conn_keywords[i] = token1;
635 conn_values[i] = token2;
636 i++;
637 }
638 else
639 {
640 /* Bogus options syntax ... ignore trailing garbage */
641 str = token1 + e;
642 }
643 }
644 }
645
646 Assert(i <= connect_params);
647 conn_keywords[i] = NULL; /* terminator */
648
649 this->connection = PQconnectdbParams(conn_keywords, conn_values, 0);
650
651 if (host)
652 ecpg_free(host);
653 if (port)
655 if (options)
657 if (dbname)
659 ecpg_free(conn_values);
660 ecpg_free(conn_keywords);
661
662 if (PQstatus(this->connection) == CONNECTION_BAD)
663 {
664 const char *errmsg = PQerrorMessage(this->connection);
665 const char *db = realname ? realname : ecpg_gettext("<DEFAULT>");
666
667 /* PQerrorMessage's result already has a trailing newline */
668 ecpg_log("ECPGconnect: %s", errmsg);
669
670 ecpg_finish(this);
672
674 if (realname)
675 ecpg_free(realname);
676
677 return false;
678 }
679
680 if (realname)
681 ecpg_free(realname);
682
684
685 this->autocommit = autocommit;
686
688
689 return true;
690}
691
692bool
693ECPGdisconnect(int lineno, const char *connection_name)
694{
695 struct sqlca_t *sqlca = ECPGget_sqlca();
696 struct connection *con;
697
698 if (sqlca == NULL)
699 {
702 return false;
703 }
704
706
707 if (strcmp(connection_name, "ALL") == 0)
708 {
710 for (con = all_connections; con;)
711 {
712 struct connection *f = con;
713
714 con = con->next;
715 ecpg_finish(f);
716 }
717 }
718 else
719 {
720 con = ecpg_get_connection_nr(connection_name);
721
722 if (!ecpg_init(con, connection_name, lineno))
723 {
725 return false;
726 }
727 else
728 ecpg_finish(con);
729 }
730
732
733 return true;
734}
735
736PGconn *
737ECPGget_PGconn(const char *connection_name)
738{
739 struct connection *con;
740
741 con = ecpg_get_connection(connection_name);
742 if (con == NULL)
743 return NULL;
744
745 return con->connection;
746}
static int32 next
Definition: blutils.c:224
static struct connection * ecpg_get_connection_nr(const char *connection_name)
Definition: connect.c:36
static void ecpg_finish(struct connection *act)
Definition: connect.c:108
static pthread_mutex_t connections_mutex
Definition: connect.c:17
void ecpg_pthreads_init(void)
Definition: connect.c:30
static pthread_key_t actual_connection_key
Definition: connect.c:18
static struct connection * all_connections
Definition: connect.c:21
PGconn * ECPGget_PGconn(const char *connection_name)
Definition: connect.c:737
bool ECPGsetconn(int lineno, const char *connection_name)
Definition: connect.c:195
bool ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
Definition: connect.c:158
bool ECPGdisconnect(int lineno, const char *connection_name)
Definition: connect.c:693
static void ECPGnoticeReceiver(void *arg, const PGresult *result)
Definition: connect.c:208
static pthread_once_t actual_connection_key_once
Definition: connect.c:19
static struct connection * actual_connection
Definition: connect.c:20
bool ECPGconnect(int lineno, int c, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
Definition: connect.c:260
struct connection * ecpg_get_connection(const char *connection_name)
Definition: connect.c:76
static void ecpg_actual_connection_init(void)
Definition: connect.c:24
bool autocommit
Definition: ecpg.c:15
enum COMPAT_MODE compat
Definition: ecpg.c:26
#define ECPG_WARNING_IN_TRANSACTION
Definition: ecpgerrno.h:72
#define ECPG_WARNING_UNKNOWN_PORTAL
Definition: ecpgerrno.h:70
#define ECPG_WARNING_PORTAL_EXISTS
Definition: ecpgerrno.h:77
#define ECPG_WARNING_NO_TRANSACTION
Definition: ecpgerrno.h:75
#define ECPG_OUT_OF_MEMORY
Definition: ecpgerrno.h:15
#define ECPG_CONNECT
Definition: ecpgerrno.h:51
#define ECPG_SQLSTATE_NO_ACTIVE_SQL_TRANSACTION
bool ecpg_check_PQresult(PGresult *results, int lineno, PGconn *connection, enum COMPAT_MODE compat)
Definition: error.c:281
#define ecpg_gettext(x)
bool ecpg_deallocate_all_conn(int lineno, enum COMPAT_MODE c, struct connection *con)
Definition: prepare.c:363
#define ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY
COMPAT_MODE
@ ECPG_COMPAT_PGSQL
char * ecpg_strdup(const char *string, int lineno, bool *alloc_failed)
Definition: memory.c:54
char * ecpg_alloc(long size, int lineno)
Definition: memory.c:19
#define ECPG_SQLSTATE_ECPG_INTERNAL_ERROR
#define ECPG_SQLSTATE_INVALID_CURSOR_NAME
void ecpg_log(const char *format,...) pg_attribute_printf(1
void ecpg_clear_auto_mem(void)
Definition: memory.c:160
bool ecpg_init(const struct connection *con, const char *connection_name, const int lineno)
Definition: misc.c:73
#define ECPG_SQLSTATE_ACTIVE_SQL_TRANSACTION
#define INFORMIX_MODE(X)
#define ECPG_SQLSTATE_DUPLICATE_CURSOR
void ecpg_init_sqlca(struct sqlca_t *sqlca)
Definition: misc.c:67
struct var_list * ivlist
Definition: misc.c:535
#define ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION
void ecpg_raise(int line, int code, const char *sqlstate, const char *str)
Definition: error.c:13
bool ecpg_internal_regression_mode
Definition: misc.c:29
void ecpg_free(void *ptr)
Definition: memory.c:13
int errmsg(const char *fmt,...)
Definition: elog.c:1071
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
Definition: fe-connect.c:7624
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:7616
void PQfinish(PGconn *conn)
Definition: fe-connect.c:5305
PQnoticeReceiver PQsetNoticeReceiver(PGconn *conn, PQnoticeReceiver proc, void *arg)
Definition: fe-connect.c:7843
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7679
PGconn * PQconnectdbParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:768
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2273
Assert(PointerIsAligned(start, uint64))
const char * str
#define free(a)
Definition: header.h:65
struct sqlca_t * ECPGget_sqlca(void)
Definition: misc.c:108
int a
Definition: isn.c:73
int i
Definition: isn.c:77
#define PQclear
Definition: libpq-be-fe.h:245
#define PQresultErrorField
Definition: libpq-be-fe.h:249
@ CONNECTION_BAD
Definition: libpq-fe.h:85
@ PQTRANS_IDLE
Definition: libpq-fe.h:147
void * arg
static PgChecksumMode mode
Definition: pg_checksums.c:55
static char * user
Definition: pg_regress.c:119
static int port
Definition: pg_regress.c:115
char * last_dir_separator(const char *filename)
Definition: path.c:145
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:58
char * c
e
Definition: preproc-init.c:82
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:60
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:42
void pthread_setspecific(pthread_key_t key, void *val)
Definition: pthread-win32.c:24
void * pthread_getspecific(pthread_key_t key)
Definition: pthread-win32.c:29
#define PTHREAD_MUTEX_INITIALIZER
Definition: pthread-win32.h:16
ULONG pthread_key_t
Definition: pthread-win32.h:7
int pthread_once_t
Definition: pthread-win32.h:18
#define sqlca
Definition: sqlca.h:59
char * dbname
Definition: streamutil.c:49
struct ECPGtype_information_cache * next
PGconn * connection
struct ECPGtype_information_cache * cache_head
struct connection * next
struct prepared_statement * prep_stmts
Definition: sqlca.h:20
char sqlstate[5]
Definition: sqlca.h:53
long sqlcode
Definition: sqlca.h:23
struct var_list * next
const char * name
#define locale_t
Definition: win32_port.h:432