Attached is a patch for temp tables that implements Tom's requests.

> Bruce Momjian <[EMAIL PROTECTED]> writes:
> >> But, when a temp rel is dropped it seems that heap_drop_with_catalog also
> >> drops the indexes, so the error occurs when index_drop is called (at least
> >> I think this is the case). Certainly commenting out the last two lines
> >> *seems* to work.
> 
> > Not sure why I introduced that bug in 1.18.  Your suggestion was 100%
> > correct.  I have applied the following patch.
> 
> Actually, I don't think this is the true explanation.  index_drop'ing
> the temp indexes may not be *necessary*, but it shouldn't *hurt* either.
> 
> Now that I think about it, the reason for the failure is probably that
> there's no CommandCounterIncrement in this loop.  Therefore, when we
> index_drop an index, the resulting system-table updates are *not seen*
> by heap_drop_with_catalog when it comes time to drop the owning table,
> and so it tries to drop the index again.
> 
> Your solution of not doing index_drop at all is sufficient for the
> table-and-index case, but I bet it is not sufficient for more complex
> cases like RI checks between temp relations.  I'd recommend doing
> CommandCounterIncrement after each temp item is dropped, instead.
> 
> There is another potential bug here: remove_all_temp_relations() is
> failing to consider the possibility that removing one list entry may
> cause other ones (eg, indexes) to go away.  It's holding onto a "next"
> pointer to a list entry that may not be there by the time control comes
> back from heap_drop_with_catalog.  This is probably OK for tables and
> indexes because the indexes will always be added after their table and
> thus appear earlier in the list, but again it seems like trouble just
> waiting to happen.  I would recommend logic along the lines of
> 
>       while (temp_rels != NIL)
>       {
>               get first entry in temp_rels,
>               and either heap_drop or index_drop it as appropriate;
>               CommandCounterIncrement();
>       }
> 
> This relies on the drop to come back and remove the temp_rels entry
> (and, possibly, other entries); so it's not an infinite loop even
> though it looks like one.
> 
>                       regards, tom lane
> 


-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  [EMAIL PROTECTED]               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
? config.log
? config.cache
? config.status
? GNUmakefile
? src/Makefile.custom
? src/GNUmakefile
? src/Makefile.global
? src/log
? src/crtags
? src/backend/postgres
? src/backend/catalog/global.bki
? src/backend/catalog/global.description
? src/backend/catalog/template1.bki
? src/backend/catalog/template1.description
? src/backend/port/Makefile
? src/bin/x
? src/bin/initdb/initdb
? src/bin/initlocation/initlocation
? src/bin/ipcclean/ipcclean
? src/bin/pg_config/pg_config
? src/bin/pg_ctl/pg_ctl
? src/bin/pg_dump/pg_dump
? src/bin/pg_dump/pg_restore
? src/bin/pg_dump/pg_dumpall
? src/bin/pg_id/pg_id
? src/bin/pg_passwd/pg_passwd
? src/bin/pgaccess/pgaccess
? src/bin/pgtclsh/Makefile.tkdefs
? src/bin/pgtclsh/Makefile.tcldefs
? src/bin/pgtclsh/pgtclsh
? src/bin/pgtclsh/pgtksh
? src/bin/psql/psql
? src/bin/scripts/createlang
? src/include/config.h
? src/include/stamp-h
? src/interfaces/ecpg/lib/libecpg.so.3.2.0
? src/interfaces/ecpg/preproc/ecpg
? src/interfaces/libpgeasy/libpgeasy.so.2.1
? src/interfaces/libpgtcl/libpgtcl.so.2.1
? src/interfaces/libpq/libpq.so.2.1
? src/interfaces/perl5/blib
? src/interfaces/perl5/Makefile
? src/interfaces/perl5/pm_to_blib
? src/interfaces/perl5/Pg.c
? src/interfaces/perl5/Pg.bs
? src/pl/plpgsql/src/libplpgsql.so.1.0
? src/pl/tcl/Makefile.tcldefs
? src/test/regress/pg_regress
? src/test/regress/regress.out
? src/test/regress/results
? src/test/regress/regression.diffs
? src/test/regress/expected/copy.out
? src/test/regress/expected/create_function_1.out
? src/test/regress/expected/create_function_2.out
? src/test/regress/expected/misc.out
? src/test/regress/expected/constraints.out
? src/test/regress/sql/copy.sql
? src/test/regress/sql/misc.sql
? src/test/regress/sql/create_function_1.sql
? src/test/regress/sql/create_function_2.sql
? src/test/regress/sql/constraints.sql
Index: src/backend/access/transam/xact.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/access/transam/xact.c,v
retrieving revision 1.71
diff -c -r1.71 xact.c
*** src/backend/access/transam/xact.c   2000/09/27 10:41:55     1.71
--- src/backend/access/transam/xact.c   2000/10/11 21:22:55
***************
*** 1119,1125 ****
        AtEOXact_portals();
        RecordTransactionAbort();
        RelationPurgeLocalRelation(false);
!       invalidate_temp_relations();
        AtEOXact_SPI();
        AtEOXact_nbtree();
        AtAbort_Cache();
--- 1119,1125 ----
        AtEOXact_portals();
        RecordTransactionAbort();
        RelationPurgeLocalRelation(false);
!       remove_temp_rel_in_myxid();
        AtEOXact_SPI();
        AtEOXact_nbtree();
        AtAbort_Cache();
Index: src/backend/catalog/heap.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/catalog/heap.c,v
retrieving revision 1.147
diff -c -r1.147 heap.c
*** src/backend/catalog/heap.c  2000/10/05 19:48:21     1.147
--- src/backend/catalog/heap.c  2000/10/11 21:22:59
***************
*** 131,141 ****
        MaxCommandIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
  };
  
! /* 
     We decide to call this attribute "tableoid" rather than say
  "classoid" on the basis that in the future there may be more than one
  table of a particular class/type. In any case table is still the word
! used in SQL. 
  */
  static FormData_pg_attribute a7 = {
        0xffffffff, {"tableoid"}, OIDOID, 0, sizeof(Oid),
--- 131,141 ----
        MaxCommandIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
  };
  
! /*
     We decide to call this attribute "tableoid" rather than say
  "classoid" on the basis that in the future there may be more than one
  table of a particular class/type. In any case table is still the word
! used in SQL.
  */
  static FormData_pg_attribute a7 = {
        0xffffffff, {"tableoid"}, OIDOID, 0, sizeof(Oid),
***************
*** 1489,1495 ****
        RelationForgetRelation(rid);
  
        if (istemp)
!               remove_temp_relation(rid);
  
        if (has_toasttable)
        {
--- 1489,1495 ----
        RelationForgetRelation(rid);
  
        if (istemp)
!               remove_temp_rel_by_relid(rid);
  
        if (has_toasttable)
        {
Index: src/backend/catalog/index.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/catalog/index.c,v
retrieving revision 1.127
diff -c -r1.127 index.c
*** src/backend/catalog/index.c 2000/10/05 19:48:21     1.127
--- src/backend/catalog/index.c 2000/10/11 21:23:00
***************
*** 1145,1151 ****
        RelationForgetRelation(indexId);
  
        /* does something only if it is a temp index */
!       remove_temp_relation(indexId);
  }
  
  /* ----------------------------------------------------------------
--- 1145,1151 ----
        RelationForgetRelation(indexId);
  
        /* does something only if it is a temp index */
!       remove_temp_rel_by_relid(indexId);
  }
  
  /* ----------------------------------------------------------------
***************
*** 1374,1380 ****
        if (!LockClassinfoForUpdate(relid, &tuple, &buffer, confirmCommitted))
                elog(ERROR, "IndexesAreActive couldn't lock %u", relid);
        if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION &&
!           ((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_TOASTVALUE)
                elog(ERROR, "relation %u isn't an indexable relation", relid);
        isactive = ((Form_pg_class) GETSTRUCT(&tuple))->relhasindex;
        ReleaseBuffer(buffer);
--- 1374,1380 ----
        if (!LockClassinfoForUpdate(relid, &tuple, &buffer, confirmCommitted))
                elog(ERROR, "IndexesAreActive couldn't lock %u", relid);
        if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION &&
!               ((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_TOASTVALUE)
                elog(ERROR, "relation %u isn't an indexable relation", relid);
        isactive = ((Form_pg_class) GETSTRUCT(&tuple))->relhasindex;
        ReleaseBuffer(buffer);
Index: src/backend/utils/cache/temprel.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/utils/cache/temprel.c,v
retrieving revision 1.27
diff -c -r1.27 temprel.c
*** src/backend/utils/cache/temprel.c   2000/07/12 18:04:45     1.27
--- src/backend/utils/cache/temprel.c   2000/10/11 21:23:01
***************
*** 91,125 ****
  void
  remove_all_temp_relations(void)
  {
-       List       *l,
-                          *next;
- 
-       if (temp_rels == NIL)
-               return;
- 
        AbortOutOfAnyTransaction();
        StartTransactionCommand();
  
!       l = temp_rels;
!       while (l != NIL)
        {
!               TempTable  *temp_rel = (TempTable *) lfirst(l);
  
!               next = lnext(l);                /* do this first, l is deallocated */
! 
!               /* Indexes are dropped during heap drop */
                if (temp_rel->relkind != RELKIND_INDEX)
-               {
-                       char            relname[NAMEDATALEN];
- 
-                       /* safe from deallocation */
-                       strcpy(relname, temp_rel->user_relname);
                        heap_drop_with_catalog(relname, allowSystemTableMods);
!               }
! 
!               l = next;
        }
-       temp_rels = NIL;
        CommitTransactionCommand();
  }
  
--- 91,112 ----
  void
  remove_all_temp_relations(void)
  {
        AbortOutOfAnyTransaction();
        StartTransactionCommand();
  
!       while (temp_rels != NIL)
        {
!               char            relname[NAMEDATALEN];
!               TempTable  *temp_rel = (TempTable *) lfirst(temp_rels);
  
!               /* safe from deallocation */
!               strcpy(relname, temp_rel->user_relname);
                if (temp_rel->relkind != RELKIND_INDEX)
                        heap_drop_with_catalog(relname, allowSystemTableMods);
!               else
!                       index_drop(temp_rel->relid);
!               CommandCounterIncrement();
        }
        CommitTransactionCommand();
  }
  
***************
*** 129,135 ****
   * we don't have the relname for indexes, so we just pass the oid
   */
  void
! remove_temp_relation(Oid relid)
  {
        MemoryContext oldcxt;
        List       *l,
--- 116,122 ----
   * we don't have the relname for indexes, so we just pass the oid
   */
  void
! remove_temp_rel_by_relid(Oid relid)
  {
        MemoryContext oldcxt;
        List       *l,
***************
*** 179,185 ****
   * We just have to delete the map entry.
   */
  void
! invalidate_temp_relations(void)
  {
        MemoryContext oldcxt;
        List       *l,
--- 166,172 ----
   * We just have to delete the map entry.
   */
  void
! remove_temp_rel_in_myxid(void)
  {
        MemoryContext oldcxt;
        List       *l,
Index: src/include/utils/temprel.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/utils/temprel.h,v
retrieving revision 1.10
diff -c -r1.10 temprel.h
*** src/include/utils/temprel.h 2000/06/20 06:41:11     1.10
--- src/include/utils/temprel.h 2000/10/11 21:23:14
***************
*** 18,29 ****
  
  extern void create_temp_relation(const char *relname,
                                                                 HeapTuple 
pg_class_tuple);
! extern void remove_temp_relation(Oid relid);
  extern bool rename_temp_relation(const char *oldname,
                                                                 const char *newname);
  
  extern void remove_all_temp_relations(void);
! extern void invalidate_temp_relations(void);
  
  extern char *get_temp_rel_by_username(const char *user_relname);
  extern char *get_temp_rel_by_physicalname(const char *relname);
--- 18,29 ----
  
  extern void create_temp_relation(const char *relname,
                                                                 HeapTuple 
pg_class_tuple);
! extern void remove_temp_rel_by_relid(Oid relid);
  extern bool rename_temp_relation(const char *oldname,
                                                                 const char *newname);
  
  extern void remove_all_temp_relations(void);
! extern void remove_temp_rel_in_myxid(void);
  
  extern char *get_temp_rel_by_username(const char *user_relname);
  extern char *get_temp_rel_by_physicalname(const char *relname);

Reply via email to