Re: [HACKERS] ECPG, threading and pooling

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: PostgreSQL-patches <pgsql-patches(at)postgresql(dot)org>
Cc: Lee Kindness <lkindness(at)csl(dot)co(dot)uk>, Michael Meskes <meskes(at)postgresql(dot)org>, "Shridhar Daithankar<shridhar_daithankar(at)persistent(dot)co(dot)in>" <shridhar_daithankar(at)persistent(dot)co(dot)in>
Subject: Re: [HACKERS] ECPG, threading and pooling
Date: 2003-06-15 04:56:32
Message-ID: 200306150456.h5F4uW401699@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-patches


I had to make the following changes to the patch. You had this:

sqlca = pthread_getspecific(&sqlca_key);

but my prototypes say it should be:

sqlca = pthread_getspecific(sqlca_key);

The applied patch also includes some prototype cleanups.

---------------------------------------------------------------------------

pgman wrote:
>
> Patch applied. I made adjustments to use the new configure thread
> settings, and I added documentation. I also updated the interface
> version numbers as included in the patch.
>
> ---------------------------------------------------------------------------
>
> Lee Kindness wrote:
> Content-Description: message body text
>
> > Michael,
> >
> > Michael Meskes writes:
> > > On Thu, Jan 23, 2003 at 02:40:33PM +0530, Shridhar Daithankar<shridhar_daithankar(at)persistent(dot)co(dot)in> wrote:
> > > > I would like to use ECPG as it is relatively easy to code. However my
> > > > application is multithreaded and also uses connecion pools.
> > >
> > > I'm afraid it needs some work to be thread-safe. sqlca is defined
> > > statically. No big deal it seems to implement a thread safe version but
> > > I haven't yet found the time.
> >
> > I've spent a bit of time on making ecpg thread safe over Christmas,
> > while it's not finished i'm sure the attached patch is at least useful
> > and a step in the right direction.
> >
> > Lee.
> >
>
> [ Attachment, skipping... ]
>
> >
> > ---------------------------(end of broadcast)---------------------------
> > TIP 3: if posting/reading through Usenet, please send an appropriate
> > subscribe-nomail command to majordomo(at)postgresql(dot)org so that your
> > message can get through to the mailing list cleanly
>
> --
> Bruce Momjian | http://candle.pha.pa.us
> pgman(at)candle(dot)pha(dot)pa(dot)us | (610) 359-1001
> + If your life is a hard drive, | 13 Roberts Road
> + Christ can be your backup. | Newtown Square, Pennsylvania 19073

> Index: configure.in
> ===================================================================
> RCS file: /cvsroot/pgsql-server/configure.in,v
> retrieving revision 1.264
> diff -c -c -r1.264 configure.in
> *** configure.in 14 Jun 2003 19:21:42 -0000 1.264
> --- configure.in 15 Jun 2003 04:02:55 -0000
> ***************
> *** 323,330 ****
> # 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)])])
>
> AC_MSG_RESULT([$with_threads])
> AC_SUBST(with_threads)
> --- 323,330 ----
> # Enable libpq to be thread-safe
> #
> AC_MSG_CHECKING([allow threaded libpq])
> ! 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)
> Index: doc/src/sgml/ecpg.sgml
> ===================================================================
> RCS file: /cvsroot/pgsql-server/doc/src/sgml/ecpg.sgml,v
> retrieving revision 1.43
> diff -c -c -r1.43 ecpg.sgml
> *** doc/src/sgml/ecpg.sgml 25 Mar 2003 16:15:35 -0000 1.43
> --- doc/src/sgml/ecpg.sgml 15 Jun 2003 04:02:56 -0000
> ***************
> *** 750,755 ****
> --- 750,762 ----
> </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.
> Embedded SQL programs are typically named with an extension
> Index: doc/src/sgml/installation.sgml
> ===================================================================
> RCS file: /cvsroot/pgsql-server/doc/src/sgml/installation.sgml,v
> retrieving revision 1.134
> diff -c -c -r1.134 installation.sgml
> *** doc/src/sgml/installation.sgml 13 Jun 2003 23:10:07 -0000 1.134
> --- doc/src/sgml/installation.sgml 15 Jun 2003 04:02:59 -0000
> ***************
> *** 918,924 ****
> <term><option>--with-threads</option></term>
> <listitem>
> <para>
> ! Allow separate libpq threads to safely control their private connection handles.
> </para>
> </listitem>
> </varlistentry>
> --- 918,925 ----
> <term><option>--with-threads</option></term>
> <listitem>
> <para>
> ! Allow separate libpq and ecpg threads to safely control their
> ! private connection handles.
> </para>
> </listitem>
> </varlistentry>
> Index: src/interfaces/ecpg/ecpglib/Makefile
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/Makefile,v
> retrieving revision 1.3
> diff -c -c -r1.3 Makefile
> *** src/interfaces/ecpg/ecpglib/Makefile 22 May 2003 17:20:44 -0000 1.3
> --- src/interfaces/ecpg/ecpglib/Makefile 15 Jun 2003 04:03:01 -0000
> ***************
> *** 13,27 ****
> include $(top_builddir)/src/Makefile.global
>
> NAME= ecpg
> ! SO_MAJOR_VERSION= 3
> ! SO_MINOR_VERSION= 4.2
>
> ! override CPPFLAGS := -I$(top_srcdir)/src/interfaces/ecpg/include -I$(libpq_srcdir) $(CPPFLAGS)
>
> 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)
>
> all: all-lib
>
> --- 13,27 ----
> include $(top_builddir)/src/Makefile.global
>
> NAME= ecpg
> ! SO_MAJOR_VERSION= 4
> ! SO_MINOR_VERSION= 1.1
>
> ! 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) $(THREAD_LIBS)
>
> all: all-lib
>
> Index: src/interfaces/ecpg/ecpglib/connect.c
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/connect.c,v
> retrieving revision 1.6
> diff -c -c -r1.6 connect.c
> *** src/interfaces/ecpg/ecpglib/connect.c 13 Jun 2003 10:50:57 -0000 1.6
> --- src/interfaces/ecpg/ecpglib/connect.c 15 Jun 2003 04:03:01 -0000
> ***************
> *** 1,29 ****
> /* $Header: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/connect.c,v 1.6 2003/06/13 10:50:57 meskes Exp $ */
>
> #include "postgres_fe.h"
>
> #include "ecpgtype.h"
> #include "ecpglib.h"
> #include "ecpgerrno.h"
> #include "extern.h"
> #include "sqlca.h"
>
> ! static struct connection *all_connections = NULL,
> ! *actual_connection = NULL;
>
> struct connection *
> ECPGget_connection(const char *connection_name)
> {
> ! struct connection *con = all_connections;
>
> ! if (connection_name == NULL || strcmp(connection_name, "CURRENT") == 0)
> ! return actual_connection;
>
> ! for (; con && strcmp(connection_name, con->name) != 0; con = con->next);
> ! if (con)
> ! return con;
> ! else
> ! return NULL;
> }
>
> static void
> --- 1,53 ----
> /* $Header: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/connect.c,v 1.6 2003/06/13 10:50:57 meskes 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"
>
> ! #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 *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;
> ! }
> !
> ! #ifdef USE_THREADS
> ! pthread_mutex_unlock(&connections_mutex);
> ! #endif
>
> ! return( ret );
> }
>
> static void
> ***************
> *** 37,42 ****
> --- 61,70 ----
> 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;
> ***************
> *** 118,134 ****
> 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);
>
> /* remove trailing newline */
> ! if (sqlca.sqlerrm.sqlerrml
> ! && sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml - 1] == '\n')
> {
> ! sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml - 1] = 0;
> ! sqlca.sqlerrm.sqlerrml--;
> }
>
> ECPGlog("raising sqlcode %d\n", code);
> --- 146,163 ----
> static void
> ECPGnoticeProcessor_raise(int code, const char *message)
> {
> ! 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')
> {
> ! sqlca->sqlerrm.sqlerrmc[sqlca->sqlerrm.sqlerrml - 1] = 0;
> ! sqlca->sqlerrm.sqlerrml--;
> }
>
> ECPGlog("raising sqlcode %d\n", code);
> ***************
> *** 141,146 ****
> --- 170,177 ----
> static void
> ECPGnoticeProcessor(void *arg, const char *message)
> {
> + struct sqlca_t *sqlca = ECPGget_sqlca();
> +
> /* these notices raise an error */
> if (strncmp(message, "WARNING: ", 9))
> {
> ***************
> *** 245,251 ****
> if (strstr(message, "cannot be rolled back"))
> return;
>
> ! /* 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! */
> --- 276,282 ----
> if (strstr(message, "cannot be rolled back"))
> return;
>
> ! /* 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! */
> ***************
> *** 253,266 ****
> /* WARNING: identifier "*" will be truncated to "*" */
> /* WARNING: InvalidateSharedInvalid: cache state reset */
> /* WARNING: RegisterSharedInvalid: SI buffer overflow */
> ! 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 connection *this;
> char *dbname = strdup(name),
> *host = NULL,
> --- 284,298 ----
> /* WARNING: identifier "*" will be truncated to "*" */
> /* WARNING: InvalidateSharedInvalid: cache state reset */
> /* WARNING: RegisterSharedInvalid: SI buffer overflow */
> ! 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,
> ***************
> *** 269,275 ****
> *realname = NULL,
> *options = NULL;
>
> ! ECPGinit_sqlca();
>
> if ((this = (struct connection *) ECPGalloc(sizeof(struct connection), lineno)) == NULL)
> return false;
> --- 301,307 ----
> *realname = NULL,
> *options = NULL;
>
> ! ECPGinit_sqlca(sqlca);
>
> if ((this = (struct connection *) ECPGalloc(sizeof(struct connection), lineno)) == NULL)
> return false;
> ***************
> *** 394,399 ****
> --- 426,434 ----
> 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
> ***************
> *** 424,429 ****
> --- 459,467 ----
>
> 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>",
> ***************
> *** 445,450 ****
> --- 483,491 ----
> ECPGfree(dbname);
> return false;
> }
> + #ifdef USE_THREADS
> + pthread_mutex_unlock(&connections_mutex);
> + #endif
>
> if (host)
> ECPGfree(host);
> ***************
> *** 468,478 ****
> bool
> ECPGdisconnect(int lineno, const char *connection_name)
> {
> struct connection *con;
>
> if (strcmp(connection_name, "ALL") == 0)
> {
> ! ECPGinit_sqlca();
> for (con = all_connections; con;)
> {
> struct connection *f = con;
> --- 509,524 ----
> 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(sqlca);
> for (con = all_connections; con;)
> {
> struct connection *f = con;
> ***************
> *** 486,495 ****
> con = ECPGget_connection(connection_name);
>
> if (!ECPGinit(con, connection_name, lineno))
> ! return (false);
> else
> ! ecpg_finish(con);
> }
>
> return true;
> }
> --- 532,550 ----
> con = ECPGget_connection(connection_name);
>
> if (!ECPGinit(con, connection_name, lineno))
> ! {
> ! #ifdef USE_THREADS
> ! pthread_mutex_unlock(&connections_mutex);
> ! #endif
> ! return (false);
> ! }
> else
> ! ecpg_finish(con);
> }
> +
> + #ifdef USE_THREADS
> + pthread_mutex_unlock(&connections_mutex);
> + #endif
>
> return true;
> }
> Index: src/interfaces/ecpg/ecpglib/data.c
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/data.c,v
> retrieving revision 1.4
> diff -c -c -r1.4 data.c
> *** src/interfaces/ecpg/ecpglib/data.c 1 Apr 2003 14:37:25 -0000 1.4
> --- src/interfaces/ecpg/ecpglib/data.c 15 Jun 2003 04:03:01 -0000
> ***************
> *** 1,5 ****
> --- 1,6 ----
> /* $Header: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/data.c,v 1.4 2003/04/01 14:37:25 meskes Exp $ */
>
> + #define POSTGRES_ECPG_INTERNAL
> #include "postgres_fe.h"
>
> #include <stdlib.h>
> ***************
> *** 21,26 ****
> --- 22,28 ----
> 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);
> ***************
> *** 328,334 ****
> default:
> break;
> }
> ! sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
> }
> }
> break;
> --- 330,336 ----
> default:
> break;
> }
> ! sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
> }
> }
> break;
> ***************
> *** 373,379 ****
> default:
> break;
> }
> ! sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
>
> variable->len = varcharsize;
> }
> --- 375,381 ----
> default:
> break;
> }
> ! sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
>
> variable->len = varcharsize;
> }
> Index: src/interfaces/ecpg/ecpglib/descriptor.c
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/descriptor.c,v
> retrieving revision 1.2
> diff -c -c -r1.2 descriptor.c
> *** src/interfaces/ecpg/ecpglib/descriptor.c 30 May 2003 13:22:02 -0000 1.2
> --- src/interfaces/ecpg/ecpglib/descriptor.c 15 Jun 2003 04:03:02 -0000
> ***************
> *** 3,8 ****
> --- 3,9 ----
> * $Header: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.2 2003/05/30 13:22:02 meskes Exp $
> */
>
> + #define POSTGRES_ECPG_INTERNAL
> #include "postgres_fe.h"
> #include "pg_type.h"
>
> ***************
> *** 51,64 ****
> ECPGget_desc_header(int lineno, char *desc_name, int *count)
> {
> PGresult *ECPGresult;
>
> ! ECPGinit_sqlca();
> ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
> if (!ECPGresult)
> return false;
>
> *count = PQnfields(ECPGresult);
> ! sqlca.sqlerrd[2] = 1;
> ECPGlog("ECPGget_desc_header: found %d attributes.\n", *count);
> return true;
> }
> --- 52,66 ----
> ECPGget_desc_header(int lineno, char *desc_name, int *count)
> {
> PGresult *ECPGresult;
> + struct sqlca_t *sqlca = ECPGget_sqlca();
>
> ! ECPGinit_sqlca(sqlca);
> ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
> if (!ECPGresult)
> return false;
>
> *count = PQnfields(ECPGresult);
> ! sqlca->sqlerrd[2] = 1;
> ECPGlog("ECPGget_desc_header: found %d attributes.\n", *count);
> return true;
> }
> ***************
> *** 149,157 ****
> int ntuples,
> act_tuple;
> struct variable data_var;
>
> va_start(args, index);
> ! ECPGinit_sqlca();
> ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
> if (!ECPGresult)
> return (false);
> --- 151,160 ----
> int ntuples,
> act_tuple;
> struct variable data_var;
> + struct sqlca_t *sqlca = ECPGget_sqlca();
>
> va_start(args, index);
> ! ECPGinit_sqlca(sqlca);
> ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
> if (!ECPGresult)
> return (false);
> ***************
> *** 378,384 ****
> ECPGlog("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index));
> }
> }
> ! sqlca.sqlerrd[2] = ntuples;
> return (true);
> }
>
> --- 381,387 ----
> ECPGlog("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index));
> }
> }
> ! sqlca->sqlerrd[2] = ntuples;
> return (true);
> }
>
> ***************
> *** 387,394 ****
> {
> struct descriptor *i;
> struct descriptor **lastptr = &all_descriptors;
>
> ! ECPGinit_sqlca();
> for (i = all_descriptors; i; lastptr = &i->next, i = i->next)
> {
> if (!strcmp(name, i->name))
> --- 390,398 ----
> {
> struct descriptor *i;
> struct descriptor **lastptr = &all_descriptors;
> + struct sqlca_t *sqlca = ECPGget_sqlca();
>
> ! ECPGinit_sqlca(sqlca);
> for (i = all_descriptors; i; lastptr = &i->next, i = i->next)
> {
> if (!strcmp(name, i->name))
> ***************
> *** 408,415 ****
> ECPGallocate_desc(int line, const char *name)
> {
> struct descriptor *new;
>
> ! ECPGinit_sqlca();
> new = (struct descriptor *) ECPGalloc(sizeof(struct descriptor), line);
> if (!new)
> return false;
> --- 412,420 ----
> ECPGallocate_desc(int line, const char *name)
> {
> struct descriptor *new;
> + struct sqlca_t *sqlca = ECPGget_sqlca();
>
> ! ECPGinit_sqlca(sqlca);
> new = (struct descriptor *) ECPGalloc(sizeof(struct descriptor), line);
> if (!new)
> return false;
> Index: src/interfaces/ecpg/ecpglib/error.c
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/error.c,v
> retrieving revision 1.1
> diff -c -c -r1.1 error.c
> *** src/interfaces/ecpg/ecpglib/error.c 16 Mar 2003 10:42:53 -0000 1.1
> --- src/interfaces/ecpg/ecpglib/error.c 15 Jun 2003 04:03:02 -0000
> ***************
> *** 1,5 ****
> --- 1,6 ----
> /* $Header: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/error.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
>
> + #define POSTGRES_ECPG_INTERNAL
> #include "postgres_fe.h"
>
> #include <stdio.h>
> ***************
> *** 17,133 ****
> void
> ECPGraise(int line, int code, const char *str)
> {
> ! sqlca.sqlcode = code;
>
> switch (code)
> {
> case ECPG_NOT_FOUND:
> ! 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),
> "Out of memory in line %d.", line);
> break;
>
> case ECPG_UNSUPPORTED:
> ! 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),
> "Too many arguments in line %d.", line);
> break;
>
> case ECPG_TOO_FEW_ARGUMENTS:
> ! 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),
> "Not correctly formatted int type: %s line %d.", str, line);
> break;
>
> case ECPG_UINT_FORMAT:
> ! 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),
> "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),
> "Unable to convert %s to bool on line %d.", str, line);
> break;
>
> case ECPG_EMPTY:
> ! 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),
> "NULL value without indicator in line %d.", line);
> break;
>
> case ECPG_NO_ARRAY:
> ! 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),
> "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),
> "Trying to insert an array of variables in line %d.", line);
> break;
>
> case ECPG_NO_CONN:
> ! 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),
> "Not connected to '%s' in line %d.", str, line);
> break;
>
> case ECPG_INVALID_STMT:
> ! 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),
> "Descriptor %s not found in line %d.", str, line);
> break;
>
> case ECPG_INVALID_DESCRIPTOR_INDEX:
> ! 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),
> "Unknown descriptor item %s in line %d.", str, line);
> break;
>
> case ECPG_VAR_NOT_NUMERIC:
> ! 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),
> "Variable is not a character type in line %d.", line);
> break;
>
> --- 18,135 ----
> void
> ECPGraise(int line, int code, const char *str)
> {
> ! struct sqlca_t *sqlca = ECPGget_sqlca();
> ! sqlca->sqlcode = code;
>
> switch (code)
> {
> case ECPG_NOT_FOUND:
> ! 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),
> "Out of memory in line %d.", line);
> break;
>
> case ECPG_UNSUPPORTED:
> ! 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),
> "Too many arguments in line %d.", line);
> break;
>
> case ECPG_TOO_FEW_ARGUMENTS:
> ! 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),
> "Not correctly formatted int type: %s line %d.", str, line);
> break;
>
> case ECPG_UINT_FORMAT:
> ! 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),
> "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),
> "Unable to convert %s to bool on line %d.", str, line);
> break;
>
> case ECPG_EMPTY:
> ! 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),
> "NULL value without indicator in line %d.", line);
> break;
>
> case ECPG_NO_ARRAY:
> ! 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),
> "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),
> "Trying to insert an array of variables in line %d.", line);
> break;
>
> case ECPG_NO_CONN:
> ! 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),
> "Not connected to '%s' in line %d.", str, line);
> break;
>
> case ECPG_INVALID_STMT:
> ! 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),
> "Descriptor %s not found in line %d.", str, line);
> break;
>
> case ECPG_INVALID_DESCRIPTOR_INDEX:
> ! 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),
> "Unknown descriptor item %s in line %d.", str, line);
> break;
>
> case ECPG_VAR_NOT_NUMERIC:
> ! 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),
> "Variable is not a character type in line %d.", line);
> break;
>
> ***************
> *** 138,166 ****
> /* strip trailing newline */
> if (slen > 0 && str[slen - 1] == '\n')
> slen--;
> ! 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),
> "Error in transaction processing in line %d.", line);
> break;
>
> case ECPG_CONNECT:
> ! 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),
> "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);
>
> /* free all memory we have allocated for the user */
> ECPGfree_auto_mem();
> --- 140,168 ----
> /* strip trailing newline */
> if (slen > 0 && str[slen - 1] == '\n')
> slen--;
> ! 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),
> "Error in transaction processing in line %d.", line);
> break;
>
> case ECPG_CONNECT:
> ! 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),
> "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);
>
> /* free all memory we have allocated for the user */
> ECPGfree_auto_mem();
> ***************
> *** 193,198 ****
> void
> sqlprint(void)
> {
> ! sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
> ! fprintf(stderr, "sql error %s\n", sqlca.sqlerrm.sqlerrmc);
> }
> --- 195,202 ----
> void
> sqlprint(void)
> {
> ! struct sqlca_t *sqlca = ECPGget_sqlca();
> !
> ! sqlca->sqlerrm.sqlerrmc[sqlca->sqlerrm.sqlerrml] = '\0';
> ! fprintf(stderr, "sql error %s\n", sqlca->sqlerrm.sqlerrmc);
> }
> Index: src/interfaces/ecpg/ecpglib/execute.c
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/execute.c,v
> retrieving revision 1.9
> diff -c -c -r1.9 execute.c
> *** src/interfaces/ecpg/ecpglib/execute.c 13 Jun 2003 10:50:57 -0000 1.9
> --- src/interfaces/ecpg/ecpglib/execute.c 15 Jun 2003 04:03:02 -0000
> ***************
> *** 13,18 ****
> --- 13,19 ----
> /* Taken over as part of PostgreSQL by Michael Meskes <meskes(at)postgresql(dot)org>
> on Feb. 5th, 1998 */
>
> + #define POSTGRES_ECPG_INTERNAL
> #include "postgres_fe.h"
>
> #include <stdio.h>
> ***************
> *** 31,64 ****
> #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.
> */
> --- 32,37 ----
> ***************
> *** 1130,1135 ****
> --- 1103,1110 ----
> */
> {
> bool clear_result = TRUE;
> + struct sqlca_t *sqlca = ECPGget_sqlca();
> +
> errmsg = PQresultErrorMessage(results);
> set_backend_err(errmsg, stmt->lineno);
>
> ***************
> *** 1142,1148 ****
>
> case PGRES_TUPLES_OK:
> nfields = PQnfields(results);
> ! sqlca.sqlerrd[2] = ntuples = PQntuples(results);
> status = true;
>
> if (ntuples < 1)
> --- 1117,1123 ----
>
> case PGRES_TUPLES_OK:
> nfields = PQnfields(results);
> ! sqlca->sqlerrd[2] = ntuples = PQntuples(results);
> status = true;
>
> if (ntuples < 1)
> ***************
> *** 1199,1208 ****
> case PGRES_COMMAND_OK:
> status = true;
> cmdstat = PQcmdStatus(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)
> || !strncmp(cmdstat, "INSERT", 6)
> || !strncmp(cmdstat, "DELETE", 6)))
> ECPGraise(stmt->lineno, ECPG_NOT_FOUND, NULL);
> --- 1174,1183 ----
> case PGRES_COMMAND_OK:
> status = true;
> cmdstat = PQcmdStatus(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)
> || !strncmp(cmdstat, "INSERT", 6)
> || !strncmp(cmdstat, "DELETE", 6)))
> ECPGraise(stmt->lineno, ECPG_NOT_FOUND, NULL);
> Index: src/interfaces/ecpg/ecpglib/extern.h
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/extern.h,v
> retrieving revision 1.1
> diff -c -c -r1.1 extern.h
> *** src/interfaces/ecpg/ecpglib/extern.h 16 Mar 2003 10:42:53 -0000 1.1
> --- src/interfaces/ecpg/ecpglib/extern.h 15 Jun 2003 04:03:02 -0000
> ***************
> *** 3,8 ****
> --- 3,9 ----
>
> #include "postgres_fe.h"
> #include "libpq-fe.h"
> + #include "sqlca.h"
>
> /* Here are some methods used by the lib. */
>
> ***************
> *** 19,25 ****
> 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 *);
> --- 20,25 ----
> Index: src/interfaces/ecpg/ecpglib/memory.c
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/memory.c,v
> retrieving revision 1.1
> diff -c -c -r1.1 memory.c
> *** src/interfaces/ecpg/ecpglib/memory.c 16 Mar 2003 10:42:53 -0000 1.1
> --- src/interfaces/ecpg/ecpglib/memory.c 15 Jun 2003 04:03:02 -0000
> ***************
> *** 1,5 ****
> --- 1,6 ----
> /* $Header: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/memory.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
>
> + #define POSTGRES_ECPG_INTERNAL
> #include "postgres_fe.h"
>
> #include "ecpgtype.h"
> Index: src/interfaces/ecpg/ecpglib/misc.c
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/misc.c,v
> retrieving revision 1.2
> diff -c -c -r1.2 misc.c
> *** src/interfaces/ecpg/ecpglib/misc.c 21 Mar 2003 15:31:04 -0000 1.2
> --- src/interfaces/ecpg/ecpglib/misc.c 15 Jun 2003 04:03:03 -0000
> ***************
> *** 1,20 ****
> /* $Header: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/misc.c,v 1.2 2003/03/21 15:31:04 meskes Exp $ */
>
> #include "postgres_fe.h"
>
> #include <unistd.h>
> #include "ecpgtype.h"
> #include "ecpglib.h"
> #include "ecpgerrno.h"
> #include "extern.h"
> #include "sqlca.h"
>
> ! static struct sqlca sqlca_init =
> {
> {
> 'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
> },
> ! sizeof(struct sqlca),
> 0,
> {
> 0,
> --- 1,24 ----
> /* $Header: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/misc.c,v 1.2 2003/03/21 15:31:04 meskes 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_t sqlca_init =
> {
> {
> 'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
> },
> ! sizeof(struct sqlca_t),
> 0,
> {
> 0,
> ***************
> *** 36,54 ****
> }
> };
>
> ! static int simple_debug = 0;
> static FILE *debugstream = NULL;
>
> ! void
> ! ECPGinit_sqlca(void)
> {
> ! memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
> }
>
> bool
> ECPGinit(const struct connection * con, const char *connection_name, const int lineno)
> {
> ! ECPGinit_sqlca();
> if (con == NULL)
> {
> ECPGraise(lineno, ECPG_NO_CONN, connection_name ? connection_name : "NULL");
> --- 40,93 ----
> }
> };
>
> ! #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(struct sqlca_t *sqlca)
> {
> ! memcpy((char *)sqlca, (char *)&sqlca_init, sizeof(struct sqlca_t));
> }
>
> bool
> ECPGinit(const struct connection * con, const char *connection_name, const int lineno)
> {
> ! struct sqlca_t *sqlca = ECPGget_sqlca();
> ! ECPGinit_sqlca(sqlca);
> if (con == NULL)
> {
> ECPGraise(lineno, ECPG_NO_CONN, connection_name ? connection_name : "NULL");
> ***************
> *** 58,63 ****
> --- 97,129 ----
> 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)
> {
> ***************
> *** 123,131 ****
> --- 189,205 ----
> 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
> ***************
> *** 133,144 ****
> {
> va_list ap;
>
> ! if (simple_debug)
> ! {
> ! char *f = (char *) malloc(strlen(format) + 100);
>
> ! if (!f)
> return;
>
> sprintf(f, "[%d]: %s", (int) getpid(), format);
>
> --- 207,226 ----
> {
> va_list ap;
>
> ! #ifdef USE_THREADS
> ! pthread_mutex_lock(&debug_mutex);
> ! #endif
>
> ! 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);
>
> ***************
> *** 148,151 ****
> --- 230,237 ----
>
> ECPGfree(f);
> }
> +
> + #ifdef USE_THREADS
> + pthread_mutex_unlock(&debug_mutex);
> + #endif
> }
> Index: src/interfaces/ecpg/ecpglib/prepare.c
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/prepare.c,v
> retrieving revision 1.1
> diff -c -c -r1.1 prepare.c
> *** src/interfaces/ecpg/ecpglib/prepare.c 16 Mar 2003 10:42:53 -0000 1.1
> --- src/interfaces/ecpg/ecpglib/prepare.c 15 Jun 2003 04:03:03 -0000
> ***************
> *** 1,5 ****
> --- 1,6 ----
> /* $Header: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/prepare.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
>
> + #define POSTGRES_ECPG_INTERNAL
> #include "postgres_fe.h"
>
> #include <ctype.h>
> Index: src/interfaces/ecpg/ecpglib/typename.c
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/typename.c,v
> retrieving revision 1.3
> diff -c -c -r1.3 typename.c
> *** src/interfaces/ecpg/ecpglib/typename.c 27 Mar 2003 14:29:17 -0000 1.3
> --- src/interfaces/ecpg/ecpglib/typename.c 15 Jun 2003 04:03:03 -0000
> ***************
> *** 1,5 ****
> --- 1,6 ----
> /* $Header: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/typename.c,v 1.3 2003/03/27 14:29:17 meskes Exp $ */
>
> + #define POSTGRES_ECPG_INTERNAL
> #include "postgres_fe.h"
>
> #include <stdlib.h>
> Index: src/interfaces/ecpg/include/sqlca.h
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/include/sqlca.h,v
> retrieving revision 1.23
> diff -c -c -r1.23 sqlca.h
> *** src/interfaces/ecpg/include/sqlca.h 18 Apr 2003 01:03:42 -0000 1.23
> --- src/interfaces/ecpg/include/sqlca.h 15 Jun 2003 04:03:03 -0000
> ***************
> *** 16,22 ****
> {
> #endif
>
> ! struct sqlca
> {
> char sqlcaid[8];
> long sqlabc;
> --- 16,22 ----
> {
> #endif
>
> ! struct sqlca_t
> {
> char sqlcaid[8];
> long sqlabc;
> ***************
> *** 53,60 ****
> char sqlext[8];
> };
>
> ! extern DLLIMPORT struct sqlca sqlca;
>
>
> #ifdef __cplusplus
> }
> --- 53,63 ----
> char sqlext[8];
> };
>
> ! struct sqlca_t *ECPGget_sqlca(void);
>
> + #ifndef POSTGRES_ECPG_INTERNAL
> + # define sqlca (*ECPGget_sqlca())
> + #endif
>
> #ifdef __cplusplus
> }
> Index: src/interfaces/ecpg/preproc/Makefile
> ===================================================================
> RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/preproc/Makefile,v
> retrieving revision 1.91
> diff -c -c -r1.91 Makefile
> *** src/interfaces/ecpg/preproc/Makefile 18 Mar 2003 10:46:39 -0000 1.91
> --- src/interfaces/ecpg/preproc/Makefile 15 Jun 2003 04:03:03 -0000
> ***************
> *** 4,11 ****
> top_builddir = ../../../..
> include $(top_builddir)/src/Makefile.global
>
> ! MAJOR_VERSION=2
> ! MINOR_VERSION=12
> PATCHLEVEL=0
>
> override CPPFLAGS := -I$(srcdir)/../include -I$(srcdir) $(CPPFLAGS) \
> --- 4,11 ----
> top_builddir = ../../../..
> include $(top_builddir)/src/Makefile.global
>
> ! MAJOR_VERSION=3
> ! MINOR_VERSION=0
> PATCHLEVEL=0
>
> override CPPFLAGS := -I$(srcdir)/../include -I$(srcdir) $(CPPFLAGS) \

--
Bruce Momjian | http://candle.pha.pa.us
pgman(at)candle(dot)pha(dot)pa(dot)us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073

Attachment Content-Type Size
unknown_filename text/plain 3.1 KB

Browse pgsql-patches by date

  From Date Subject
Next Message deststar 2003-06-15 15:18:45 ecpg compile (compatlib)
Previous Message Bruce Momjian 2003-06-15 04:07:12 Re: [HACKERS] ECPG, threading and pooling