11/* dynamic SQL support routines
22 *
3- * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.23 2007/08/14 10:01:52 meskes Exp $
3+ * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.24 2007/10/02 09:49:59 meskes Exp $
44 */
55
66#define POSTGRES_ECPG_INTERNAL
77#include "postgres_fe.h"
88#include "pg_type.h"
99
10+ #include "ecpg-pthread-win32.h"
1011#include "ecpgtype.h"
1112#include "ecpglib.h"
1213#include "ecpgerrno.h"
1314#include "extern.h"
1415#include "sqlca.h"
1516#include "sql3types.h"
1617
17- struct descriptor * all_descriptors = NULL ;
18+ static void descriptor_free (struct descriptor * desc );
19+ static void descriptor_deallocate_all (struct descriptor * list );
20+
21+ /* We manage descriptors separately for each thread. */
22+ #ifdef ENABLE_THREAD_SAFETY
23+ static pthread_key_t descriptor_key ;
24+ #ifndef WIN32
25+ static pthread_once_t descriptor_once = PTHREAD_ONCE_INIT ;
26+ #endif
27+
28+ static void
29+ descriptor_destructor (void * arg )
30+ {
31+ descriptor_deallocate_all (arg );
32+ }
33+
34+ NON_EXEC_STATIC void
35+ descriptor_key_init (void )
36+ {
37+ pthread_key_create (& descriptor_key ,descriptor_destructor );
38+ }
39+
40+ static struct descriptor *
41+ get_descriptors (void )
42+ {
43+ pthread_once (& descriptor_once ,descriptor_key_init );
44+ return (struct descriptor * )pthread_getspecific (descriptor_key );
45+ }
46+
47+ static void
48+ set_descriptors (struct descriptor * value )
49+ {
50+ pthread_setspecific (descriptor_key ,value );
51+ }
52+
53+ #else
54+ static struct descriptor * all_descriptors = NULL ;
55+ #define get_descriptors ()(all_descriptors)
56+ #define set_descriptors (value )do { all_descriptors = (value); } while(0)
57+ #endif
1858
1959/* old internal convenience function that might go away later */
20- static PGresult
21- *
60+ static PGresult *
2261ECPGresultByDescriptor (int line ,const char * name )
2362{
24- PGresult * * resultpp = ECPGdescriptor_lvalue (line ,name );
25-
26- if (resultpp )
27- return * resultpp ;
28- return NULL ;
63+ struct descriptor * desc = ECPGfind_desc (line ,name );
64+ if (desc == NULL )
65+ return NULL ;
66+ return desc -> result ;
2967}
3068
3169static unsignedint
@@ -445,20 +483,9 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
445483bool
446484ECPGset_desc_header (int lineno ,const char * desc_name ,int count )
447485{
448- struct descriptor * desc ;
449-
450- for (desc = all_descriptors ;desc ;desc = desc -> next )
451- {
452- if (strcmp (desc_name ,desc -> name )== 0 )
453- break ;
454- }
455-
486+ struct descriptor * desc = ECPGfind_desc (lineno ,desc_name );
456487if (desc == NULL )
457- {
458- ECPGraise (lineno ,ECPG_UNKNOWN_DESCRIPTOR ,ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME ,desc_name );
459488return false;
460- }
461-
462489desc -> count = count ;
463490return true;
464491}
@@ -471,17 +498,9 @@ ECPGset_desc(int lineno, const char *desc_name, int index,...)
471498struct descriptor_item * desc_item ;
472499struct variable * var ;
473500
474- for (desc = all_descriptors ;desc ;desc = desc -> next )
475- {
476- if (strcmp (desc_name ,desc -> name )== 0 )
477- break ;
478- }
479-
501+ desc = ECPGfind_desc (lineno ,desc_name );
480502if (desc == NULL )
481- {
482- ECPGraise (lineno ,ECPG_UNKNOWN_DESCRIPTOR ,ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME ,desc_name );
483503return false;
484- }
485504
486505for (desc_item = desc -> items ;desc_item ;desc_item = desc_item -> next )
487506{
@@ -506,7 +525,7 @@ ECPGset_desc(int lineno, const char *desc_name, int index,...)
506525
507526va_start (args ,index );
508527
509- do
528+ for (;;)
510529{
511530enum ECPGdtype itemtype ;
512531const char * tobeinserted = NULL ;
@@ -585,47 +604,69 @@ ECPGset_desc(int lineno, const char *desc_name, int index,...)
585604return false;
586605}
587606}
588- }while (true);
607+ }
589608ECPGfree (var );
590609
591610return true;
592611}
593612
613+ /* Free the descriptor and items in it. */
614+ static void
615+ descriptor_free (struct descriptor * desc )
616+ {
617+ struct descriptor_item * desc_item ;
618+
619+ for (desc_item = desc -> items ;desc_item ;)
620+ {
621+ struct descriptor_item * di ;
622+
623+ ECPGfree (desc_item -> data );
624+ di = desc_item ;
625+ desc_item = desc_item -> next ;
626+ ECPGfree (di );
627+ }
628+
629+ ECPGfree (desc -> name );
630+ PQclear (desc -> result );
631+ ECPGfree (desc );
632+ }
633+
594634bool
595635ECPGdeallocate_desc (int line ,const char * name )
596636{
597637struct descriptor * desc ;
598- struct descriptor * * lastptr = & all_descriptors ;
638+ struct descriptor * prev ;
599639struct sqlca_t * sqlca = ECPGget_sqlca ();
600640
601641ECPGinit_sqlca (sqlca );
602- for (desc = all_descriptors ;desc ;lastptr = & desc -> next ,desc = desc -> next )
642+ for (desc = get_descriptors (), prev = NULL ;desc ;prev = desc ,desc = desc -> next )
603643{
604644if (!strcmp (name ,desc -> name ))
605645{
606- struct descriptor_item * desc_item ;
607-
608- for (desc_item = desc -> items ;desc_item ;)
609- {
610- struct descriptor_item * di ;
611-
612- ECPGfree (desc_item -> data );
613- di = desc_item ;
614- desc_item = desc_item -> next ;
615- ECPGfree (di );
616- }
617-
618- * lastptr = desc -> next ;
619- ECPGfree (desc -> name );
620- PQclear (desc -> result );
621- ECPGfree (desc );
646+ if (prev )
647+ prev -> next = desc -> next ;
648+ else
649+ set_descriptors (desc -> next );
650+ descriptor_free (desc );
622651return true;
623652}
624653}
625654ECPGraise (line ,ECPG_UNKNOWN_DESCRIPTOR ,ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME ,name );
626655return false;
627656}
628657
658+ /* Deallocate all descriptors in the list */
659+ static void
660+ descriptor_deallocate_all (struct descriptor * list )
661+ {
662+ while (list )
663+ {
664+ struct descriptor * next = list -> next ;
665+ descriptor_free (list );
666+ list = next ;
667+ }
668+ }
669+
629670bool
630671ECPGallocate_desc (int line ,const char * name )
631672{
@@ -636,7 +677,7 @@ ECPGallocate_desc(int line, const char *name)
636677new = (struct descriptor * )ECPGalloc (sizeof (struct descriptor ),line );
637678if (!new )
638679return false;
639- new -> next = all_descriptors ;
680+ new -> next = get_descriptors () ;
640681new -> name = ECPGalloc (strlen (name )+ 1 ,line );
641682if (!new -> name )
642683{
@@ -654,23 +695,24 @@ ECPGallocate_desc(int line, const char *name)
654695return false;
655696}
656697strcpy (new -> name ,name );
657- all_descriptors = new ;
698+ set_descriptors ( new ) ;
658699return true;
659700}
660701
661- PGresult * *
662- ECPGdescriptor_lvalue (int line ,const char * descriptor )
702+ /* Find descriptor with name in the connection. */
703+ struct descriptor *
704+ ECPGfind_desc (int line ,const char * name )
663705{
664- struct descriptor * i ;
706+ struct descriptor * desc ;
665707
666- for (i = all_descriptors ; i != NULL ; i = i -> next )
708+ for (desc = get_descriptors (); desc ; desc = desc -> next )
667709{
668- if (! strcmp (descriptor , i -> name ))
669- return & i -> result ;
710+ if (strcmp (name , desc -> name )== 0 )
711+ return desc ;
670712}
671713
672- ECPGraise (line ,ECPG_UNKNOWN_DESCRIPTOR ,ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME ,( char * ) descriptor );
673- return NULL ;
714+ ECPGraise (line ,ECPG_UNKNOWN_DESCRIPTOR ,ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME ,name );
715+ return NULL ;/* not found */
674716}
675717
676718bool