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

Generated by: LCOV version 1.14