dnl Process this file with autoconf to produce a configure script.
-dnl $Header: /cvsroot/pgsql/configure.in,v 1.264 2003/06/14 19:21:42 momjian Exp $
+dnl $Header: /cvsroot/pgsql/configure.in,v 1.265 2003/06/15 04:07:58 momjian Exp $
dnl
dnl Developers, please strive to achieve this order:
dnl
# Enable libpq to be thread-safe
#
AC_MSG_CHECKING([allow threaded libpq])
-PGAC_ARG_BOOL(with, threads, no, [ --with-threads allow libpq to be thread-safe],
- [AC_DEFINE([USE_THREADS], 1, [Define to 1 to build libpq with threads. (--with-threads)])])
+PGAC_ARG_BOOL(with, threads, no, [ --with-threads allow libpq and ecpg to be thread-safe],
+ [AC_DEFINE([USE_THREADS], 1, [Define to 1 to build libpq and ecpg to be thread-safe. (--with-threads)])])
AC_MSG_RESULT([$with_threads])
AC_SUBST(with_threads)
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.43 2003/03/25 16:15:35 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.44 2003/06/15 04:07:58 momjian Exp $
-->
<chapter id="ecpg">
in the arguments specified for output.
</para>
+ <para>
+ <application>ecpg</application> is thread-safe if it is compiled using
+ the <literal>--with-threads</> <filename>configure</filename>
+ command-line option. (You might need to use other threading
+ command-line options to compile your client code.)
+ </para>
+
<para>
The preprocessor program is called <filename>ecpg</filename> and is
included in a normal <productname>PostgreSQL</> installation.
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.134 2003/06/13 23:10:07 momjian Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.135 2003/06/15 04:07:58 momjian Exp $ -->
<chapter id="installation">
<title><![%standalone-include[<productname>PostgreSQL</>]]>
<term><option>--with-threads</option></term>
<listitem>
<para>
- Allow separate libpq threads to safely control their private connection handles.
+ Allow separate libpq and ecpg threads to safely control their
+ private connection handles.
</para>
</listitem>
</varlistentry>
#
# Copyright (c) 1994, Regents of the University of California
#
-# $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/Makefile,v 1.3 2003/05/22 17:20:44 petere Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/Makefile,v 1.4 2003/06/15 04:07:58 momjian Exp $
#
#-------------------------------------------------------------------------
include $(top_builddir)/src/Makefile.global
NAME= ecpg
-SO_MAJOR_VERSION= 3
-SO_MINOR_VERSION= 4.2
+SO_MAJOR_VERSION= 4
+SO_MINOR_VERSION= 1.1
-override CPPFLAGS := -I$(top_srcdir)/src/interfaces/ecpg/include -I$(libpq_srcdir) $(CPPFLAGS)
+override CPPFLAGS := -I$(top_srcdir)/src/interfaces/ecpg/include -I$(libpq_srcdir) $(CPPFLAGS) $(THREAD_CFLAGS)
OBJS= execute.o typename.o descriptor.o data.o error.o prepare.o memory.o \
connect.o misc.o
-SHLIB_LINK = -L../pgtypeslib -lpgtypes $(libpq)
+SHLIB_LINK = -L../pgtypeslib -lpgtypes $(libpq) $(THREAD_LIBS)
all: all-lib
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.6 2003/06/13 10:50:57 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.7 2003/06/15 04:07:58 momjian Exp $ */
+#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
+#ifdef USE_THREADS
+#include <pthread.h>
+#endif
#include "ecpgtype.h"
#include "ecpglib.h"
#include "ecpgerrno.h"
#include "extern.h"
#include "sqlca.h"
-static struct connection *all_connections = NULL,
- *actual_connection = NULL;
+#ifdef USE_THREADS
+static pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+static struct connection *all_connections = NULL;
+static struct connection *actual_connection = NULL;
struct connection *
ECPGget_connection(const char *connection_name)
{
- struct connection *con = all_connections;
+ struct connection *ret = NULL;
+
+#ifdef USE_THREADS
+ pthread_mutex_lock(&connections_mutex);
+#endif
+
+ if( (connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0) )
+ {
+ ret = actual_connection;
+ }
+ else
+ {
+ struct connection *con;
+
+ for( con = all_connections; con != NULL; con = con->next)
+ {
+ if( strcmp(connection_name, con->name) == 0 )
+ break;
+ }
+ ret = con;
+ }
- if (connection_name == NULL || strcmp(connection_name, "CURRENT") == 0)
- return actual_connection;
+#ifdef USE_THREADS
+ pthread_mutex_unlock(&connections_mutex);
+#endif
- for (; con && strcmp(connection_name, con->name) != 0; con = con->next);
- if (con)
- return con;
- else
- return NULL;
+ return( ret );
}
static void
ECPGlog("ecpg_finish: finishing %s.\n", act->name);
PQfinish(act->connection);
+ /* no need to lock connections_mutex - we're always called
+ by ECPGdisconnect or ECPGconnect, which are holding
+ the lock */
+
/* remove act from the list */
if (act == all_connections)
all_connections = act->next;
static void
ECPGnoticeProcessor_raise(int code, const char *message)
{
- sqlca.sqlcode = code;
- strncpy(sqlca.sqlerrm.sqlerrmc, message, sizeof(sqlca.sqlerrm.sqlerrmc));
- sqlca.sqlerrm.sqlerrmc[sizeof(sqlca.sqlerrm.sqlerrmc) - 1] = 0;
- sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);
+ struct sqlca_t *sqlca = ECPGget_sqlca();
+ sqlca->sqlcode = code;
+ strncpy(sqlca->sqlerrm.sqlerrmc, message, sizeof(sqlca->sqlerrm.sqlerrmc));
+ sqlca->sqlerrm.sqlerrmc[sizeof(sqlca->sqlerrm.sqlerrmc) - 1] = 0;
+ sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
/* remove trailing newline */
- if (sqlca.sqlerrm.sqlerrml
- && sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml - 1] == '\n')
+ if (sqlca->sqlerrm.sqlerrml
+ && sqlca->sqlerrm.sqlerrmc[sqlca->sqlerrm.sqlerrml - 1] == '\n')
{
- sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml - 1] = 0;
- sqlca.sqlerrm.sqlerrml--;
+ sqlca->sqlerrm.sqlerrmc[sqlca->sqlerrm.sqlerrml - 1] = 0;
+ sqlca->sqlerrm.sqlerrml--;
}
ECPGlog("raising sqlcode %d\n", code);
static void
ECPGnoticeProcessor(void *arg, const char *message)
{
+ struct sqlca_t *sqlca = ECPGget_sqlca();
+
/* these notices raise an error */
if (strncmp(message, "WARNING: ", 9))
{
if (strstr(message, "cannot be rolled back"))
return;
- /* these and other unmentioned should set sqlca.sqlwarn[2] */
+ /* these and other unmentioned should set sqlca->sqlwarn[2] */
/* WARNING: The ':' operator is deprecated. Use exp(x) instead. */
/* WARNING: Rel *: Uninitialized page 0 - fixing */
/* WARNING: PortalHeapMemoryFree: * not in alloc set! */
/* WARNING: identifier "*" will be truncated to "*" */
/* WARNING: InvalidateSharedInvalid: cache state reset */
/* WARNING: RegisterSharedInvalid: SI buffer overflow */
- sqlca.sqlwarn[2] = 'W';
- sqlca.sqlwarn[0] = 'W';
+ sqlca->sqlwarn[2] = 'W';
+ sqlca->sqlwarn[0] = 'W';
}
/* this contains some quick hacks, needs to be cleaned up, but it works */
bool
ECPGconnect(int lineno, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
{
+ struct sqlca_t *sqlca = ECPGget_sqlca();
struct connection *this;
char *dbname = strdup(name),
*host = NULL,
*realname = NULL,
*options = NULL;
- ECPGinit_sqlca();
+ ECPGinit_sqlca(sqlca);
if ((this = (struct connection *) ECPGalloc(sizeof(struct connection), lineno)) == NULL)
return false;
realname = strdup(dbname);
/* add connection to our list */
+#ifdef USE_THREADS
+ pthread_mutex_lock(&connections_mutex);
+#endif
if (connection_name != NULL)
this->name = ECPGstrdup(connection_name, lineno);
else
set_backend_err(errmsg, lineno);
ecpg_finish(this);
+#ifdef USE_THREADS
+ pthread_mutex_unlock(&connections_mutex);
+#endif
ECPGlog("connect: could not open database %s on %s port %s %s%s%s%s in line %d\n\t%s\n",
db,
host ? host : "<DEFAULT>",
ECPGfree(dbname);
return false;
}
+#ifdef USE_THREADS
+ pthread_mutex_unlock(&connections_mutex);
+#endif
if (host)
ECPGfree(host);
bool
ECPGdisconnect(int lineno, const char *connection_name)
{
+ struct sqlca_t *sqlca = ECPGget_sqlca();
struct connection *con;
+#ifdef USE_THREADS
+ pthread_mutex_lock(&connections_mutex);
+#endif
+
if (strcmp(connection_name, "ALL") == 0)
{
- ECPGinit_sqlca();
+ ECPGinit_sqlca(sqlca);
for (con = all_connections; con;)
{
struct connection *f = con;
con = ECPGget_connection(connection_name);
if (!ECPGinit(con, connection_name, lineno))
- return (false);
+ {
+#ifdef USE_THREADS
+ pthread_mutex_unlock(&connections_mutex);
+#endif
+ return (false);
+ }
else
- ecpg_finish(con);
+ ecpg_finish(con);
}
+#ifdef USE_THREADS
+ pthread_mutex_unlock(&connections_mutex);
+#endif
+
return true;
}
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.4 2003/04/01 14:37:25 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.5 2003/06/15 04:07:58 momjian Exp $ */
+#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include <stdlib.h>
char *var, char *ind, long varcharsize, long offset,
long ind_offset, bool isarray)
{
+ struct sqlca_t *sqlca = ECPGget_sqlca();
char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld\n", lineno, pval ? pval : "", offset);
default:
break;
}
- sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
+ sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
}
}
break;
default:
break;
}
- sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
+ sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
variable->len = varcharsize;
}
/* dynamic SQL support routines
*
- * $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.2 2003/05/30 13:22:02 meskes Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.3 2003/06/15 04:07:58 momjian Exp $
*/
+#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include "pg_type.h"
ECPGget_desc_header(int lineno, char *desc_name, int *count)
{
PGresult *ECPGresult;
+ struct sqlca_t *sqlca = ECPGget_sqlca();
- ECPGinit_sqlca();
+ ECPGinit_sqlca(sqlca);
ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
if (!ECPGresult)
return false;
*count = PQnfields(ECPGresult);
- sqlca.sqlerrd[2] = 1;
+ sqlca->sqlerrd[2] = 1;
ECPGlog("ECPGget_desc_header: found %d attributes.\n", *count);
return true;
}
int ntuples,
act_tuple;
struct variable data_var;
+ struct sqlca_t *sqlca = ECPGget_sqlca();
va_start(args, index);
- ECPGinit_sqlca();
+ ECPGinit_sqlca(sqlca);
ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
if (!ECPGresult)
return (false);
ECPGlog("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index));
}
}
- sqlca.sqlerrd[2] = ntuples;
+ sqlca->sqlerrd[2] = ntuples;
return (true);
}
{
struct descriptor *i;
struct descriptor **lastptr = &all_descriptors;
+ struct sqlca_t *sqlca = ECPGget_sqlca();
- ECPGinit_sqlca();
+ ECPGinit_sqlca(sqlca);
for (i = all_descriptors; i; lastptr = &i->next, i = i->next)
{
if (!strcmp(name, i->name))
ECPGallocate_desc(int line, const char *name)
{
struct descriptor *new;
+ struct sqlca_t *sqlca = ECPGget_sqlca();
- ECPGinit_sqlca();
+ ECPGinit_sqlca(sqlca);
new = (struct descriptor *) ECPGalloc(sizeof(struct descriptor), line);
if (!new)
return false;
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/error.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/error.c,v 1.2 2003/06/15 04:07:58 momjian Exp $ */
+#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include <stdio.h>
void
ECPGraise(int line, int code, const char *str)
{
- sqlca.sqlcode = code;
+ struct sqlca_t *sqlca = ECPGget_sqlca();
+ sqlca->sqlcode = code;
switch (code)
{
case ECPG_NOT_FOUND:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"No data found in line %d.", line);
break;
case ECPG_OUT_OF_MEMORY:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Out of memory in line %d.", line);
break;
case ECPG_UNSUPPORTED:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Unsupported type %s in line %d.", str, line);
break;
case ECPG_TOO_MANY_ARGUMENTS:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Too many arguments in line %d.", line);
break;
case ECPG_TOO_FEW_ARGUMENTS:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Too few arguments in line %d.", line);
break;
case ECPG_INT_FORMAT:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Not correctly formatted int type: %s line %d.", str, line);
break;
case ECPG_UINT_FORMAT:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Not correctly formatted unsigned type: %s in line %d.", str, line);
break;
case ECPG_FLOAT_FORMAT:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Not correctly formatted floating-point type: %s in line %d.", str, line);
break;
case ECPG_CONVERT_BOOL:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Unable to convert %s to bool on line %d.", str, line);
break;
case ECPG_EMPTY:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Empty query in line %d.", line);
break;
case ECPG_MISSING_INDICATOR:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"NULL value without indicator in line %d.", line);
break;
case ECPG_NO_ARRAY:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Variable is not an array in line %d.", line);
break;
case ECPG_DATA_NOT_ARRAY:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Data read from backend is not an array in line %d.", line);
break;
case ECPG_ARRAY_INSERT:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Trying to insert an array of variables in line %d.", line);
break;
case ECPG_NO_CONN:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"No such connection %s in line %d.", str, line);
break;
case ECPG_NOT_CONN:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Not connected to '%s' in line %d.", str, line);
break;
case ECPG_INVALID_STMT:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Invalid statement name %s in line %d.", str, line);
break;
case ECPG_UNKNOWN_DESCRIPTOR:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Descriptor %s not found in line %d.", str, line);
break;
case ECPG_INVALID_DESCRIPTOR_INDEX:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Descriptor index out of range in line %d.", line);
break;
case ECPG_UNKNOWN_DESCRIPTOR_ITEM:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Unknown descriptor item %s in line %d.", str, line);
break;
case ECPG_VAR_NOT_NUMERIC:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Variable is not a numeric type in line %d.", line);
break;
case ECPG_VAR_NOT_CHAR:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Variable is not a character type in line %d.", line);
break;
/* strip trailing newline */
if (slen > 0 && str[slen - 1] == '\n')
slen--;
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"'%.*s' in line %d.", slen, str, line);
break;
}
case ECPG_TRANS:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Error in transaction processing in line %d.", line);
break;
case ECPG_CONNECT:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"Could not connect to database %s in line %d.", str, line);
break;
default:
- snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
"SQL error #%d in line %d.", code, line);
break;
}
- sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);
- ECPGlog("raising sqlcode %d in line %d, '%s'.\n", code, line, sqlca.sqlerrm.sqlerrmc);
+ sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
+ ECPGlog("raising sqlcode %d in line %d, '%s'.\n", code, line, sqlca->sqlerrm.sqlerrmc);
/* free all memory we have allocated for the user */
ECPGfree_auto_mem();
void
sqlprint(void)
{
- sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
- fprintf(stderr, "sql error %s\n", sqlca.sqlerrm.sqlerrmc);
+ struct sqlca_t *sqlca = ECPGget_sqlca();
+
+ sqlca->sqlerrm.sqlerrmc[sqlca->sqlerrm.sqlerrml] = '\0';
+ fprintf(stderr, "sql error %s\n", sqlca->sqlerrm.sqlerrmc);
}
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.9 2003/06/13 10:50:57 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.10 2003/06/15 04:07:58 momjian Exp $ */
/*
* The aim is to get a simpler inteface to the database routines.
/* Taken over as part of PostgreSQL by Michael Meskes <meskes@postgresql.org>
on Feb. 5th, 1998 */
+#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include <stdio.h>
#include "pgtypes_timestamp.h"
#include "pgtypes_interval.h"
-/* variables visible to the programs */
-struct sqlca sqlca =
-{
- {
- 'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
- },
- sizeof(struct sqlca),
- 0,
- {
- 0,
- {
- 0
- }
- },
- {
- 'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
- },
- {
- 0, 0, 0, 0, 0, 0
- },
- {
- 0, 0, 0, 0, 0, 0, 0, 0
- },
- {
- 0, 0, 0, 0, 0, 0, 0, 0
- }
-};
-
/* This function returns a newly malloced string that has the \
in the argument quoted with \ and the ' quoted with ' as SQL92 says.
*/
*/
{
bool clear_result = TRUE;
+ struct sqlca_t *sqlca = ECPGget_sqlca();
+
errmsg = PQresultErrorMessage(results);
set_backend_err(errmsg, stmt->lineno);
case PGRES_TUPLES_OK:
nfields = PQnfields(results);
- sqlca.sqlerrd[2] = ntuples = PQntuples(results);
+ sqlca->sqlerrd[2] = ntuples = PQntuples(results);
status = true;
if (ntuples < 1)
case PGRES_COMMAND_OK:
status = true;
cmdstat = PQcmdStatus(results);
- sqlca.sqlerrd[1] = PQoidValue(results);
- sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
+ sqlca->sqlerrd[1] = PQoidValue(results);
+ sqlca->sqlerrd[2] = atol(PQcmdTuples(results));
ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, cmdstat);
- if (!sqlca.sqlerrd[2] && ( !strncmp(cmdstat, "UPDATE", 6)
+ if (!sqlca->sqlerrd[2] && ( !strncmp(cmdstat, "UPDATE", 6)
|| !strncmp(cmdstat, "INSERT", 6)
|| !strncmp(cmdstat, "DELETE", 6)))
ECPGraise(stmt->lineno, ECPG_NOT_FOUND, NULL);
#include "postgres_fe.h"
#include "libpq-fe.h"
+#include "sqlca.h"
/* Here are some methods used by the lib. */
bool ECPGget_data(const PGresult *, int, int, int, enum ECPGttype type,
enum ECPGttype, char *, char *, long, long, long, bool);
struct connection *ECPGget_connection(const char *);
-void ECPGinit_sqlca(void);
char *ECPGalloc(long, int);
char *ECPGrealloc(void *, long, int);
void ECPGfree(void *);
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/memory.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/memory.c,v 1.2 2003/06/15 04:07:58 momjian Exp $ */
+#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include "ecpgtype.h"
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.2 2003/03/21 15:31:04 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.3 2003/06/15 04:07:58 momjian Exp $ */
+#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include <unistd.h>
+#ifdef USE_THREADS
+#include <pthread.h>
+#endif
#include "ecpgtype.h"
#include "ecpglib.h"
#include "ecpgerrno.h"
#include "extern.h"
#include "sqlca.h"
-static struct sqlca sqlca_init =
+static struct sqlca_t sqlca_init =
{
{
'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
},
- sizeof(struct sqlca),
+ sizeof(struct sqlca_t),
0,
{
0,
}
};
-static int simple_debug = 0;
+#ifdef USE_THREADS
+static pthread_key_t sqlca_key;
+static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT;
+#else
+static struct sqlca_t sqlca =
+{
+ {
+ 'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
+ },
+ sizeof(struct sqlca_t),
+ 0,
+ {
+ 0,
+ {
+ 0
+ }
+ },
+ {
+ 'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
+ },
+ {
+ 0, 0, 0, 0, 0, 0
+ },
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0
+ }
+};
+#endif
+
+#ifdef USE_THREADS
+static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+static int simple_debug = 0;
static FILE *debugstream = NULL;
-void
-ECPGinit_sqlca(void)
+void ECPGinit_sqlca(struct sqlca_t *sqlca)
{
- memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
+ memcpy((char *)sqlca, (char *)&sqlca_init, sizeof(struct sqlca_t));
}
bool
ECPGinit(const struct connection * con, const char *connection_name, const int lineno)
{
- ECPGinit_sqlca();
+ struct sqlca_t *sqlca = ECPGget_sqlca();
+ ECPGinit_sqlca(sqlca);
if (con == NULL)
{
ECPGraise(lineno, ECPG_NO_CONN, connection_name ? connection_name : "NULL");
return (true);
}
+#ifdef USE_THREADS
+static void ecpg_sqlca_key_init(void)
+{
+ pthread_key_create(&sqlca_key, NULL);
+}
+#endif
+
+struct sqlca_t *ECPGget_sqlca(void)
+{
+#ifdef USE_THREADS
+ struct sqlca_t *sqlca;
+
+ pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
+
+ sqlca = pthread_getspecific(&sqlca_key);
+ if( sqlca == NULL )
+ {
+ sqlca = malloc(sizeof(struct sqlca_t));
+ ECPGinit_sqlca(sqlca);
+ pthread_setspecific(&sqlca_key, sqlca);
+ }
+ return( sqlca );
+#else
+ return( &sqlca );
+#endif
+}
+
bool
ECPGstatus(int lineno, const char *connection_name)
{
void
ECPGdebug(int n, FILE *dbgs)
{
+#ifdef USE_THREADS
+ pthread_mutex_lock(&debug_mutex);
+#endif
+
simple_debug = n;
debugstream = dbgs;
ECPGlog("ECPGdebug: set to %d\n", simple_debug);
+
+#ifdef USE_THREADS
+ pthread_mutex_unlock(&debug_mutex);
+#endif
}
void
{
va_list ap;
- if (simple_debug)
- {
- char *f = (char *) malloc(strlen(format) + 100);
+#ifdef USE_THREADS
+ pthread_mutex_lock(&debug_mutex);
+#endif
- if (!f)
+ if( simple_debug )
+ {
+ char *f = (char *)malloc(strlen(format) + 100);
+ if( f == NULL )
+ {
+#ifdef USE_THREADS
+ pthread_mutex_unlock(&debug_mutex);
+#endif
return;
+ }
sprintf(f, "[%d]: %s", (int) getpid(), format);
ECPGfree(f);
}
+
+#ifdef USE_THREADS
+ pthread_mutex_unlock(&debug_mutex);
+#endif
}
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.2 2003/06/15 04:07:58 momjian Exp $ */
+#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include <ctype.h>
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/typename.c,v 1.3 2003/03/27 14:29:17 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/typename.c,v 1.4 2003/06/15 04:07:58 momjian Exp $ */
+#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include <stdlib.h>
{
#endif
-struct sqlca
+struct sqlca_t
{
char sqlcaid[8];
long sqlabc;
char sqlext[8];
};
-extern DLLIMPORT struct sqlca sqlca;
+struct sqlca_t *ECPGget_sqlca(void);
+#ifndef POSTGRES_ECPG_INTERNAL
+# define sqlca (*ECPGget_sqlca())
+#endif
#ifdef __cplusplus
}
-# $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.91 2003/03/18 10:46:39 meskes Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.92 2003/06/15 04:07:58 momjian Exp $
subdir = src/interfaces/ecpg/preproc
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
-MAJOR_VERSION=2
-MINOR_VERSION=12
+MAJOR_VERSION=3
+MINOR_VERSION=0
PATCHLEVEL=0
override CPPFLAGS := -I$(srcdir)/../include -I$(srcdir) $(CPPFLAGS) \