Thread: New DEV FAQ item

New DEV FAQ item

From
Bruce Momjian
Date:
I have added more to the last item.

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

  9) How do I efficiently access information in tables from the backend code?

   You first need to find the tuples(rows) you are interested in. There
   are two ways. First, SearchSysCacheTuple() and related functions allow
   you to query the system catalogs. This is the preferred way to access
   system tables, because the first call to the cache loads the needed
   rows, and future requests can return the results without accessing the
   base table. Some of the caches use system table indexes to look up
   tuples. A list of available caches is located in
   src/backend/utils/cache/syscache.c.
   src/backend/utils/cache/lsyscache.c contains many column-specific
   cache lookup functions.

   The rows returned are cached-owned versions of the heap rows. They are
   invalidated when the base table changes. Because the cache is local to
   each backend, you may use the pointer returned from the cache for
   short periods without making a copy of the tuple. If you send the
   pointer into a large function that will be doing its own cache
   lookups, it is possible the cache entry may be flushed, so you should
   use SearchSysCacheTupleCopy() in these cases, and pfree() the tuple
   when you are done.

   If you can't use the system cache, you will need to retrieve the data
   directly from the heap table, using the buffer cache that is shared by
   all backends. The backend automatically takes care of loading the rows
   into the buffer cache.

   Open the table with heap_open(). You can then start a table scan with
   heap_beginscan(), then use heap_getnext() and continue as long as
   HeapTupleIsValid() returns true. Then do a heap_endscan(). Keys can be
   assigned to the scan. No indexes are used, so all rows are going to be
   compared to the keys, and only the valid rows returned.

   You can also use heap_fetch() to fetch rows by block number/offset.
   While scans automatically lock/unlock rows from the buffer cache, with
   heap_fetch(), you must pass a Buffer pointer, and ReleaseBuffer() it
   when completed. Once you have the row, you can get data that is common
   to all tuples, like t_ctid and t_oid, by mererly accessing the
   HeapTuple structure entries. If you need a table-specific column, you
   should take the HeapTuple pointer, and use the GETSTRUCT() macro to
   access the table-specific start of the tuple. You then cast the
   pointer as a Form_pg_proc pointer if you are accessing the pg_proc
   table, or TypeTupleForm if you are accessing pg_type. You can then
   access the columns by using a structure pointer:

        ((Form_pg_class) GETSTRUCT(tuple))->relnatts

   You should not directly change live tuples in this way. The best way
   is to use heap_tuplemodify() and pass it your palloc'ed tuple, and the
   values you want changed. It returns another palloc'ed tuple, which you
   pass to heap_replace(). You can delete tuples by passing the tuple's
   t_ctid to heap_destroy(). Remember, tuples can be either system cache
   versions, which may go away soon after you get them, buffer cache
   version, which will go away when you heap_getnext(), heap_endscan, or
   ReleaseBuffer(), in the heap_fetch() case. Or it may be a palloc'ed
   tuple, that you must pfree() when finished.

--
Bruce Momjian                          |  830 Blythe Avenue
maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
  +  If your life is a hard drive,     |  (610) 353-9879(w)
  +  Christ can be your backup.        |  (610) 853-3000(h)