LCOV - differential code coverage report
Current view: top level - src/backend/catalog - pg_largeobject.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 97.7 % 44 43 1 43
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 3 3 3
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a