I wrote:

> The code is obviously confused between Oid and relfilenode.  The
> calculate_total_relation_size() function gets a relfilenode parameter
> and then tries to call relation_open() with it.  This is wrong.

This is the patch I'm about to apply.  Besides fixing this particular
problem, I made the code include the size of the index of the TOAST
table in pg_total_relation_size().

-- 
Alvaro Herrera                         Architect, http://www.EnterpriseDB.com
"En las profundidades de nuestro inconsciente hay una obsesiva necesidad
de un universo lógico y coherente. Pero el universo real se halla siempre
un paso más allá de la lógica" (Irulan)
Index: dbsize.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/utils/adt/dbsize.c,v
retrieving revision 1.4
diff -c -r1.4 dbsize.c
*** dbsize.c    16 Sep 2005 05:35:40 -0000      1.4
--- dbsize.c    29 Sep 2005 21:49:49 -0000
***************
*** 216,249 ****
   * calculate size of a relation
   */
  static int64
! calculate_relation_size(Oid tblspcOid, Oid relnodeOid)
  {
!       int64           totalsize=0;
!       unsigned int segcount=0;
!       char dirpath[MAXPGPATH];
!       char pathname[MAXPGPATH];
! 
!       if (!tblspcOid)
!               tblspcOid = MyDatabaseTableSpace;
! 
!       if (tblspcOid == DEFAULTTABLESPACE_OID)
!           snprintf(dirpath, MAXPGPATH, "%s/base/%u", DataDir, MyDatabaseId);
!       else if (tblspcOid == GLOBALTABLESPACE_OID)
            snprintf(dirpath, MAXPGPATH, "%s/global", DataDir);
        else
            snprintf(dirpath, MAXPGPATH, "%s/pg_tblspc/%u/%u",
!                                DataDir, tblspcOid, MyDatabaseId);
  
!       for (segcount = 0 ;; segcount++)
        {
                struct stat fst;
  
                if (segcount == 0)
                    snprintf(pathname, MAXPGPATH, "%s/%u",
!                                        dirpath, relnodeOid);
                else
                    snprintf(pathname, MAXPGPATH, "%s/%u.%u",
!                                        dirpath, relnodeOid, segcount);
  
                if (stat(pathname, &fst) < 0)
                {
--- 216,248 ----
   * calculate size of a relation
   */
  static int64
! calculate_relation_size(RelFileNode *rfn)
  {
!       int64           totalsize = 0;
!       char            dirpath[MAXPGPATH];
!       char            pathname[MAXPGPATH];
!       unsigned int segcount = 0;
! 
!       Assert(OidIsValid(rfn->spcNode));
! 
!       if (rfn->spcNode == DEFAULTTABLESPACE_OID)
!           snprintf(dirpath, MAXPGPATH, "%s/base/%u", DataDir, rfn->dbNode);
!       else if (rfn->spcNode == GLOBALTABLESPACE_OID)
            snprintf(dirpath, MAXPGPATH, "%s/global", DataDir);
        else
            snprintf(dirpath, MAXPGPATH, "%s/pg_tblspc/%u/%u",
!                                DataDir, rfn->spcNode, rfn->dbNode);
  
!       for (segcount = 0; ; segcount++)
        {
                struct stat fst;
  
                if (segcount == 0)
                    snprintf(pathname, MAXPGPATH, "%s/%u",
!                                        dirpath, rfn->relNode);
                else
                    snprintf(pathname, MAXPGPATH, "%s/%u.%u",
!                                        dirpath, rfn->relNode, segcount);
  
                if (stat(pathname, &fst) < 0)
                {
***************
*** 264,287 ****
  pg_relation_size_oid(PG_FUNCTION_ARGS)
  {
        Oid         relOid=PG_GETARG_OID(0);
!       HeapTuple   tuple;
!       Form_pg_class pg_class;
!       Oid                     relnodeOid;
!       Oid         tblspcOid;
! 
!       tuple = SearchSysCache(RELOID,
!                                                  ObjectIdGetDatum(relOid),
!                                                  0, 0, 0);
!       if (!HeapTupleIsValid(tuple))
!               elog(ERROR, "cache lookup failed for relation %u", relOid);
! 
!       pg_class = (Form_pg_class) GETSTRUCT(tuple);
!       relnodeOid = pg_class->relfilenode;
!       tblspcOid = pg_class->reltablespace;
  
!       ReleaseSysCache(tuple);
  
!       PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid));
  }
  
  Datum
--- 263,278 ----
  pg_relation_size_oid(PG_FUNCTION_ARGS)
  {
        Oid         relOid=PG_GETARG_OID(0);
!       Relation        rel;
!       int64           size;
  
!       rel = relation_open(relOid, AccessShareLock);
  
!       size = calculate_relation_size(&(rel->rd_node));
! 
!       relation_close(rel, AccessShareLock);
! 
!       PG_RETURN_INT64(size);
  }
  
  Datum
***************
*** 289,365 ****
  {
        text       *relname = PG_GETARG_TEXT_P(0);
        RangeVar   *relrv;
!       Relation        relation;
!       Oid                     relnodeOid;
!       Oid         tblspcOid;
      
        relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));    
!       relation = relation_openrv(relrv, AccessShareLock);
      
!       tblspcOid  = relation->rd_rel->reltablespace;             
!       relnodeOid = relation->rd_rel->relfilenode;
               
!       relation_close(relation, AccessShareLock);
  
!       PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid));
  }
  
  
  /*
!  *  Compute the on-disk size of files for 'relation' according to the
   *  stat function, optionally including heap data, index data, and/or
   *  toast data.
   */
  static int64
! calculate_total_relation_size(Oid tblspcOid, Oid relnodeOid)
  {
!     Relation        heapRelation;
!       Relation        idxRelation;
!       Relation        toastRelation;
!     Oid             idxOid;
!     Oid             idxTblspcOid;
!       Oid             toastOid;
!       Oid             toastTblspcOid;
!       bool            hasIndices;
!       int64           size;
!       List            *indexoidlist;
!       ListCell        *idx;
! 
!     heapRelation = relation_open(relnodeOid, AccessShareLock);
!       toastOid = heapRelation->rd_rel->reltoastrelid;
!       hasIndices = heapRelation->rd_rel->relhasindex;
  
!     /* Get the heap size */
!     size = calculate_relation_size(tblspcOid, relnodeOid);
  
!     /* Get index size */
!       if (hasIndices)
        {
                /* recursively include any dependent indexes */
!               indexoidlist = RelationGetIndexList(heapRelation);
  
!               foreach(idx, indexoidlist)
                {
!             idxOid = lfirst_oid(idx);
!                       idxRelation = relation_open(idxOid, AccessShareLock);
!             idxTblspcOid = idxRelation->rd_rel->reltablespace;
!                       size += calculate_relation_size(idxTblspcOid, idxOid);
!                       relation_close(idxRelation, AccessShareLock);
                }
!               list_free(indexoidlist);
        }
  
!     relation_close(heapRelation, AccessShareLock);
  
!     /* Get toast table size */
!       if (toastOid != 0)
!       {
!               /* recursively include any toast relations */
!               toastRelation = relation_open(toastOid, AccessShareLock);
!               toastTblspcOid = toastRelation->rd_rel->reltablespace;
!               size += calculate_relation_size(toastTblspcOid, toastOid);
!               relation_close(toastRelation, AccessShareLock);
!       }
  
        return size;
  }
--- 280,344 ----
  {
        text       *relname = PG_GETARG_TEXT_P(0);
        RangeVar   *relrv;
!       Relation        rel;
!       int64           size;
      
        relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));    
!       rel = relation_openrv(relrv, AccessShareLock);
      
!       size = calculate_relation_size(&(rel->rd_node));
               
!       relation_close(rel, AccessShareLock);
  
!       PG_RETURN_INT64(size);
  }
  
  
  /*
!  *  Compute the on-disk size of files for the relation according to the
   *  stat function, optionally including heap data, index data, and/or
   *  toast data.
   */
  static int64
! calculate_total_relation_size(Oid Relid)
  {
!       Relation        heapRel;
!       Oid                     toastOid;
!       int64           size;
!       ListCell   *cell;
  
!       heapRel = relation_open(Relid, AccessShareLock);
!       toastOid = heapRel->rd_rel->reltoastrelid;
  
!       /* Get the heap size */
!       size = calculate_relation_size(&(heapRel->rd_node));
! 
!       /* Get index size */
!       if (heapRel->rd_rel->relhasindex)
        {
                /* recursively include any dependent indexes */
!               List *index_oids = RelationGetIndexList(heapRel);
  
!               foreach(cell, index_oids)
                {
!                       Oid                     idxOid = lfirst_oid(cell);
!                       Relation        iRel;
! 
!                       iRel = relation_open(idxOid, AccessShareLock);
! 
!                       size += calculate_relation_size(&(iRel->rd_node));
! 
!                       relation_close(iRel, AccessShareLock);
                }
! 
!               list_free(index_oids);
        }
  
!       /* Get toast table (and index) size */
!       if (OidIsValid(toastOid))
!               size += calculate_total_relation_size(toastOid);
  
!       relation_close(heapRel, AccessShareLock);
  
        return size;
  }
***************
*** 371,415 ****
  Datum
  pg_total_relation_size_oid(PG_FUNCTION_ARGS)
  {
!       Oid             relOid=PG_GETARG_OID(0);
!       HeapTuple       tuple;
!       Form_pg_class   pg_class;
!       Oid             relnodeOid;
!       Oid             tblspcOid;
! 
!       tuple = SearchSysCache(RELOID,
!                                                  ObjectIdGetDatum(relOid),
!                                                  0, 0, 0);
!       if (!HeapTupleIsValid(tuple))
!               elog(ERROR, "cache lookup failed for relation %u", relOid);
! 
!       pg_class = (Form_pg_class) GETSTRUCT(tuple);
!       relnodeOid = pg_class->relfilenode;
!       tblspcOid = pg_class->reltablespace;
! 
!       ReleaseSysCache(tuple);
  
!       PG_RETURN_INT64(calculate_total_relation_size(tblspcOid, relnodeOid));
  }
  
  Datum
  pg_total_relation_size_name(PG_FUNCTION_ARGS)
  {
!       text            *relname = PG_GETARG_TEXT_P(0);
!       RangeVar        *relrv;
!       Relation        relation;
!       Oid             relnodeOid;
!       Oid             tblspcOid;
      
        relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));    
!       relation = relation_openrv(relrv, AccessShareLock);
      
!       tblspcOid  = relation->rd_rel->reltablespace;             
!       relnodeOid = relation->rd_rel->relfilenode;
!              
!       relation_close(relation, AccessShareLock);
! 
!       PG_RETURN_INT64(calculate_total_relation_size(tblspcOid, relnodeOid));
  }
  
  /*
--- 350,371 ----
  Datum
  pg_total_relation_size_oid(PG_FUNCTION_ARGS)
  {
!       Oid             relid = PG_GETARG_OID(0);
  
!       PG_RETURN_INT64(calculate_total_relation_size(relid));
  }
  
  Datum
  pg_total_relation_size_name(PG_FUNCTION_ARGS)
  {
!       text       *relname = PG_GETARG_TEXT_P(0);
!       RangeVar   *relrv;
!       Oid                     relid;
      
        relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));    
!       relid = RangeVarGetRelid(relrv, false);
      
!       PG_RETURN_INT64(calculate_total_relation_size(relid));
  }
  
  /*
***************
*** 418,454 ****
  Datum
  pg_size_pretty(PG_FUNCTION_ARGS)
  {
!       int64 size=PG_GETARG_INT64(0);
!       char *result=palloc(50+VARHDRSZ);
!       int64 limit = 10*1024;
!       int64 mult=1;
! 
!       if (size < limit*mult)
!           snprintf(VARDATA(result), 50, INT64_FORMAT" bytes",
!                                size);
        else
        {
                mult *= 1024;
!               if (size < limit*mult)
                     snprintf(VARDATA(result), 50, INT64_FORMAT " kB",
!                                         (size+mult/2) / mult);
                else
                {
                        mult *= 1024;
!                       if (size < limit*mult)
                            snprintf(VARDATA(result), 50, INT64_FORMAT " MB",
!                                                (size+mult/2) / mult);
                        else
                        {
                                mult *= 1024;
!                               if (size < limit*mult)
                                    snprintf(VARDATA(result), 50, INT64_FORMAT 
" GB",
!                                                        (size+mult/2) / mult);
                                else
                                {
                                    mult *= 1024;
                                    snprintf(VARDATA(result), 50, INT64_FORMAT 
" TB",
!                                                        (size+mult/2) / mult);
                                }
                        }
                }
--- 374,409 ----
  Datum
  pg_size_pretty(PG_FUNCTION_ARGS)
  {
!       int64   size = PG_GETARG_INT64(0);
!       char   *result = palloc(50 + VARHDRSZ);
!       int64   limit = 10 * 1024;
!       int64   mult = 1;
! 
!       if (size < limit * mult)
!           snprintf(VARDATA(result), 50, INT64_FORMAT " bytes", size);
        else
        {
                mult *= 1024;
!               if (size < limit * mult)
                     snprintf(VARDATA(result), 50, INT64_FORMAT " kB",
!                                         (size + mult / 2) / mult);
                else
                {
                        mult *= 1024;
!                       if (size < limit * mult)
                            snprintf(VARDATA(result), 50, INT64_FORMAT " MB",
!                                                (size + mult / 2) / mult);
                        else
                        {
                                mult *= 1024;
!                               if (size < limit * mult)
                                    snprintf(VARDATA(result), 50, INT64_FORMAT 
" GB",
!                                                        (size + mult / 2) / 
mult);
                                else
                                {
                                    mult *= 1024;
                                    snprintf(VARDATA(result), 50, INT64_FORMAT 
" TB",
!                                                        (size + mult / 2) / 
mult);
                                }
                        }
                }
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to