3 #define POSTGRES_ECPG_INTERNAL
4 #include "postgres_fe.h"
6 #include "ecpg-pthread-win32.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
;
18 static struct connection
*actual_connection
= NULL
;
19 static struct connection
*all_connections
= NULL
;
21 #ifdef ENABLE_THREAD_SAFETY
23 ecpg_actual_connection_init(void)
25 pthread_key_create(&actual_connection_key
, NULL
);
29 ecpg_pthreads_init(void)
31 pthread_once(&actual_connection_key_once
, ecpg_actual_connection_init
);
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 */
52 /* no TSD connection, going for global */
53 ret
= actual_connection
;
55 ret
= actual_connection
;
60 struct connection
*con
;
62 for (con
= all_connections
; con
!= NULL
; con
= con
->next
)
64 if (strcmp(connection_name
, con
->name
) == 0)
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 */
90 /* no TSD connection here either, using global */
91 ret
= actual_connection
;
93 ret
= actual_connection
;
98 #ifdef ENABLE_THREAD_SAFETY
99 pthread_mutex_lock(&connections_mutex
);
102 ret
= ecpg_get_connection_nr(connection_name
);
104 #ifdef ENABLE_THREAD_SAFETY
105 pthread_mutex_unlock(&connections_mutex
);
113 ecpg_finish(struct connection
* act
)
117 struct ECPGtype_information_cache
*cache
,
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
;
133 struct connection
*con
;
135 for (con
= all_connections
; con
->next
&& con
->next
!= act
; con
= 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
);
144 if (actual_connection
== act
)
145 actual_connection
= all_connections
;
147 ecpg_log("ecpg_finish: connection %s closed\n", act
->name
);
149 for (cache
= act
->cache_head
; cache
; ptr
= cache
, cache
= cache
->next
, ecpg_free(ptr
));
150 ecpg_free(act
->name
);
154 ecpg_log("ecpg_finish: called an extra time\n");
158 ECPGsetcommit(int lineno
, const char *mode
, const char *connection_name
)
160 struct connection
*con
= ecpg_get_connection(connection_name
);
163 if (!ecpg_init(con
, connection_name
, lineno
))
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)
172 results
= PQexec(con
->connection
, "begin transaction");
173 if (!ecpg_check_PQresult(results
, lineno
, con
->connection
, ECPG_COMPAT_PGSQL
))
176 con
->committed
= false;
178 con
->autocommit
= false;
180 else if (con
->autocommit
== false && strncmp(mode
, "on", strlen("on")) == 0)
184 results
= PQexec(con
->connection
, "commit");
185 if (!ecpg_check_PQresult(results
, lineno
, con
->connection
, ECPG_COMPAT_PGSQL
))
188 con
->committed
= true;
190 con
->autocommit
= true;
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
))
204 #ifdef ENABLE_THREAD_SAFETY
205 pthread_setspecific(actual_connection_key
, con
);
207 actual_connection
= con
;
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();
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
= _("No message received");
228 /* these are not warnings */
229 if (strncmp(sqlstate
, "00", 2) == 0)
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
;
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
);
259 strlen_or_null(const char *string
)
263 return (strlen(string
));
266 /* this contains some quick hacks, needs to be cleaned up, but it works */
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;
274 char *dbname
= name
? ecpg_strdup(name
, lineno
) : NULL
,
280 *connect_string
= NULL
;
282 ecpg_init_sqlca(sqlca
);
285 * clear auto_mem structure because some error handling functions might
288 ecpg_clear_auto_mem();
290 if (INFORMIX_MODE(compat
))
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");
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();
315 /* check if the identifier is unique */
316 if (ecpg_get_connection(connection_name
))
319 ecpg_log("ECPGconnect: connection identifier %s is already in use\n",
324 if ((this = (struct connection
*) ecpg_alloc(sizeof(struct connection
), lineno
)) == NULL
)
329 /* get the detail information out of dbname */
330 if (strncmp(dbname
, "tcp:", 4) == 0 || strncmp(dbname
, "unix:", 5) == 0)
335 * only allow protocols tcp and unix
337 if (strncmp(dbname
, "tcp:", 4) == 0)
339 else if (strncmp(dbname
, "unix:", 5) == 0)
342 if (strncmp(dbname
+ offset
, "postgresql://", strlen("postgresql://")) == 0)
347 * <tcp|unix>:postgresql://server[:port|:/unixsocket/path:]
348 * [/db name][?options]
351 offset
+= strlen("postgresql://");
353 tmp
= strrchr(dbname
+ offset
, '?');
354 if (tmp
!= NULL
) /* options given */
356 options
= ecpg_strdup(tmp
+ 1, lineno
);
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
);
368 tmp
= strrchr(dbname
+ offset
, ':');
369 if (tmp
!= NULL
) /* port number or Unix socket path given */
374 if ((tmp2
= strchr(tmp
+ 1, ':')) != NULL
)
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
: _("<DEFAULT>"));
386 * port not set yet if (port) ecpg_free(port);
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
: _("<DEFAULT>"));
423 host
= ecpg_strdup(dbname
+ offset
, lineno
);
429 /* old style: dbname[@server][:port] */
430 tmp
= strrchr(dbname
, ':');
431 if (tmp
!= NULL
) /* port number given */
433 port
= ecpg_strdup(tmp
+ 1, lineno
);
437 tmp
= strrchr(dbname
, '@');
438 if (tmp
!= NULL
) /* host name given */
440 host
= ecpg_strdup(tmp
+ 1, lineno
);
444 realname
= (strlen(dbname
) > 0) ? ecpg_strdup(dbname
, lineno
) : NULL
;
450 /* add connection to our list */
451 #ifdef ENABLE_THREAD_SAFETY
452 pthread_mutex_lock(&connections_mutex
);
454 if (connection_name
!= NULL
)
455 this->name
= ecpg_strdup(connection_name
, lineno
);
457 this->name
= ecpg_strdup(realname
, lineno
);
459 this->cache_head
= NULL
;
460 this->prep_stmts
= NULL
;
462 if (all_connections
== NULL
)
465 this->next
= all_connections
;
467 all_connections
= this;
468 #ifdef ENABLE_THREAD_SAFETY
469 pthread_setspecific(actual_connection_key
, all_connections
);
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
] == '&')
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
);
515 if (PQstatus(this->connection
) == CONNECTION_BAD
)
517 const char *errmsg
= PQerrorMessage(this->connection
);
518 const char *db
= realname
? realname
: _("<DEFAULT>");
520 ecpg_log("ECPGconnect: could not open database: %s\n", errmsg
);
523 #ifdef ENABLE_THREAD_SAFETY
524 pthread_mutex_unlock(&connections_mutex
);
527 ecpg_raise(lineno
, ECPG_CONNECT
, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION
, db
);
537 #ifdef ENABLE_THREAD_SAFETY
538 pthread_mutex_unlock(&connections_mutex
);
541 this->committed
= true;
542 this->autocommit
= autocommit
;
544 PQsetNoticeReceiver(this->connection
, &ECPGnoticeReceiver
, (void *) this);
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
);
559 if (strcmp(connection_name
, "ALL") == 0)
561 ecpg_init_sqlca(sqlca
);
562 for (con
= all_connections
; con
;)
564 struct connection
*f
= con
;
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
);
585 #ifdef ENABLE_THREAD_SAFETY
586 pthread_mutex_unlock(&connections_mutex
);
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
;