LCOV - code coverage report
Current view: top level - src/backend/catalog - pg_largeobject.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 42 43 97.7 %
Date: 2017-09-29 13:40:31 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * pg_largeobject.c
       4             :  *    routines to support manipulation of the pg_largeobject relation
       5             :  *
       6             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/catalog/pg_largeobject.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "access/genam.h"
      18             : #include "access/heapam.h"
      19             : #include "access/htup_details.h"
      20             : #include "access/sysattr.h"
      21             : #include "catalog/dependency.h"
      22             : #include "catalog/indexing.h"
      23             : #include "catalog/pg_largeobject.h"
      24             : #include "catalog/pg_largeobject_metadata.h"
      25             : #include "miscadmin.h"
      26             : #include "utils/acl.h"
      27             : #include "utils/fmgroids.h"
      28             : #include "utils/rel.h"
      29             : #include "utils/tqual.h"
      30             : 
      31             : 
      32             : /*
      33             :  * Create a large object having the given LO identifier.
      34             :  *
      35             :  * We create a new large object by inserting an entry into
      36             :  * pg_largeobject_metadata without any data pages, so that the object
      37             :  * will appear to exist with size 0.
      38             :  */
      39             : Oid
      40          15 : LargeObjectCreate(Oid loid)
      41             : {
      42             :     Relation    pg_lo_meta;
      43             :     HeapTuple   ntup;
      44             :     Oid         loid_new;
      45             :     Datum       values[Natts_pg_largeobject_metadata];
      46             :     bool        nulls[Natts_pg_largeobject_metadata];
      47             : 
      48          15 :     pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
      49             :                            RowExclusiveLock);
      50             : 
      51             :     /*
      52             :      * Insert metadata of the largeobject
      53             :      */
      54          15 :     memset(values, 0, sizeof(values));
      55          15 :     memset(nulls, false, sizeof(nulls));
      56             : 
      57             :     values[Anum_pg_largeobject_metadata_lomowner - 1]
      58          15 :         = ObjectIdGetDatum(GetUserId());
      59          15 :     nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true;
      60             : 
      61          15 :     ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta),
      62             :                            values, nulls);
      63          15 :     if (OidIsValid(loid))
      64           8 :         HeapTupleSetOid(ntup, loid);
      65             : 
      66          15 :     loid_new = CatalogTupleInsert(pg_lo_meta, ntup);
      67          15 :     Assert(!OidIsValid(loid) || loid == loid_new);
      68             : 
      69          15 :     heap_freetuple(ntup);
      70             : 
      71          15 :     heap_close(pg_lo_meta, RowExclusiveLock);
      72             : 
      73          15 :     return loid_new;
      74             : }
      75             : 
      76             : /*
      77             :  * Drop a large object having the given LO identifier.  Both the data pages
      78             :  * and metadata must be dropped.
      79             :  */
      80             : void
      81          12 : LargeObjectDrop(Oid loid)
      82             : {
      83             :     Relation    pg_lo_meta;
      84             :     Relation    pg_largeobject;
      85             :     ScanKeyData skey[1];
      86             :     SysScanDesc scan;
      87             :     HeapTuple   tuple;
      88             : 
      89          12 :     pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
      90             :                            RowExclusiveLock);
      91             : 
      92          12 :     pg_largeobject = heap_open(LargeObjectRelationId,
      93             :                                RowExclusiveLock);
      94             : 
      95             :     /*
      96             :      * Delete an entry from pg_largeobject_metadata
      97             :      */
      98          12 :     ScanKeyInit(&skey[0],
      99             :                 ObjectIdAttributeNumber,
     100             :                 BTEqualStrategyNumber, F_OIDEQ,
     101             :                 ObjectIdGetDatum(loid));
     102             : 
     103          12 :     scan = systable_beginscan(pg_lo_meta,
     104             :                               LargeObjectMetadataOidIndexId, true,
     105             :                               NULL, 1, skey);
     106             : 
     107          12 :     tuple = systable_getnext(scan);
     108          12 :     if (!HeapTupleIsValid(tuple))
     109           0 :         ereport(ERROR,
     110             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
     111             :                  errmsg("large object %u does not exist", loid)));
     112             : 
     113          12 :     CatalogTupleDelete(pg_lo_meta, &tuple->t_self);
     114             : 
     115          12 :     systable_endscan(scan);
     116             : 
     117             :     /*
     118             :      * Delete all the associated entries from pg_largeobject
     119             :      */
     120          12 :     ScanKeyInit(&skey[0],
     121             :                 Anum_pg_largeobject_loid,
     122             :                 BTEqualStrategyNumber, F_OIDEQ,
     123             :                 ObjectIdGetDatum(loid));
     124             : 
     125          12 :     scan = systable_beginscan(pg_largeobject,
     126             :                               LargeObjectLOidPNIndexId, true,
     127             :                               NULL, 1, skey);
     128        1344 :     while (HeapTupleIsValid(tuple = systable_getnext(scan)))
     129             :     {
     130        1320 :         CatalogTupleDelete(pg_largeobject, &tuple->t_self);
     131             :     }
     132             : 
     133          12 :     systable_endscan(scan);
     134             : 
     135          12 :     heap_close(pg_largeobject, RowExclusiveLock);
     136             : 
     137          12 :     heap_close(pg_lo_meta, RowExclusiveLock);
     138          12 : }
     139             : 
     140             : /*
     141             :  * LargeObjectExists
     142             :  *
     143             :  * We don't use the system cache for large object metadata, for fear of
     144             :  * using too much local memory.
     145             :  *
     146             :  * This function always scans the system catalog using an up-to-date snapshot,
     147             :  * so it should not be used when a large object is opened in read-only mode
     148             :  * (because large objects opened in read only mode are supposed to be viewed
     149             :  * relative to the caller's snapshot, whereas in read-write mode they are
     150             :  * relative to a current snapshot).
     151             :  */
     152             : bool
     153          17 : LargeObjectExists(Oid loid)
     154             : {
     155             :     Relation    pg_lo_meta;
     156             :     ScanKeyData skey[1];
     157             :     SysScanDesc sd;
     158             :     HeapTuple   tuple;
     159          17 :     bool        retval = false;
     160             : 
     161          17 :     ScanKeyInit(&skey[0],
     162             :                 ObjectIdAttributeNumber,
     163             :                 BTEqualStrategyNumber, F_OIDEQ,
     164             :                 ObjectIdGetDatum(loid));
     165             : 
     166          17 :     pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
     167             :                            AccessShareLock);
     168             : 
     169          17 :     sd = systable_beginscan(pg_lo_meta,
     170             :                             LargeObjectMetadataOidIndexId, true,
     171             :                             NULL, 1, skey);
     172             : 
     173          17 :     tuple = systable_getnext(sd);
     174          17 :     if (HeapTupleIsValid(tuple))
     175          14 :         retval = true;
     176             : 
     177          17 :     systable_endscan(sd);
     178             : 
     179          17 :     heap_close(pg_lo_meta, AccessShareLock);
     180             : 
     181          17 :     return retval;
     182             : }

Generated by: LCOV version 1.11