2000-10-24 03:38:44 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* pg_largeobject.c
|
|
|
|
* routines to support manipulation of the pg_largeobject relation
|
|
|
|
*
|
2002-06-20 22:29:54 +02:00
|
|
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
2000-10-24 03:38:44 +02:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2002-06-20 22:29:54 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.13 2002/06/20 20:29:26 momjian Exp $
|
2000-10-24 03:38:44 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include "access/genam.h"
|
|
|
|
#include "access/heapam.h"
|
|
|
|
#include "catalog/catname.h"
|
|
|
|
#include "catalog/indexing.h"
|
|
|
|
#include "catalog/pg_largeobject.h"
|
|
|
|
#include "miscadmin.h"
|
|
|
|
#include "utils/builtins.h"
|
|
|
|
#include "utils/fmgroids.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a large object having the given LO identifier.
|
|
|
|
*
|
|
|
|
* We do this by inserting an empty first page, so that the object will
|
|
|
|
* appear to exist with size 0. Note that the unique index will reject
|
|
|
|
* an attempt to create a duplicate page.
|
|
|
|
*/
|
2001-08-10 22:52:25 +02:00
|
|
|
void
|
2000-10-24 03:38:44 +02:00
|
|
|
LargeObjectCreate(Oid loid)
|
|
|
|
{
|
|
|
|
Relation pg_largeobject;
|
|
|
|
HeapTuple ntup;
|
|
|
|
Relation idescs[Num_pg_largeobject_indices];
|
|
|
|
Datum values[Natts_pg_largeobject];
|
|
|
|
char nulls[Natts_pg_largeobject];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
pg_largeobject = heap_openr(LargeObjectRelationName, RowExclusiveLock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Form new tuple
|
|
|
|
*/
|
|
|
|
for (i = 0; i < Natts_pg_largeobject; i++)
|
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
values[i] = (Datum) NULL;
|
2000-10-24 03:38:44 +02:00
|
|
|
nulls[i] = ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
values[i++] = ObjectIdGetDatum(loid);
|
|
|
|
values[i++] = Int32GetDatum(0);
|
|
|
|
values[i++] = DirectFunctionCall1(byteain,
|
|
|
|
CStringGetDatum(""));
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2000-10-24 03:38:44 +02:00
|
|
|
ntup = heap_formtuple(pg_largeobject->rd_att, values, nulls);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Insert it
|
|
|
|
*/
|
2002-05-22 00:05:55 +02:00
|
|
|
simple_heap_insert(pg_largeobject, ntup);
|
2000-10-24 03:38:44 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Update indices
|
|
|
|
*/
|
|
|
|
if (!IsIgnoringSystemIndexes())
|
|
|
|
{
|
|
|
|
CatalogOpenIndices(Num_pg_largeobject_indices, Name_pg_largeobject_indices, idescs);
|
|
|
|
CatalogIndexInsert(idescs, Num_pg_largeobject_indices, pg_largeobject, ntup);
|
|
|
|
CatalogCloseIndices(Num_pg_largeobject_indices, idescs);
|
|
|
|
}
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2000-10-24 03:38:44 +02:00
|
|
|
heap_close(pg_largeobject, RowExclusiveLock);
|
|
|
|
|
|
|
|
heap_freetuple(ntup);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
LargeObjectDrop(Oid loid)
|
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
Relation pg_largeobject;
|
|
|
|
Relation pg_lo_idx;
|
2001-03-22 05:01:46 +01:00
|
|
|
ScanKeyData skey[1];
|
2000-10-24 03:38:44 +02:00
|
|
|
IndexScanDesc sd;
|
2002-05-21 01:51:44 +02:00
|
|
|
HeapTuple tuple;
|
2000-10-24 03:38:44 +02:00
|
|
|
|
|
|
|
ScanKeyEntryInitialize(&skey[0],
|
|
|
|
(bits16) 0x0,
|
|
|
|
(AttrNumber) 1,
|
|
|
|
(RegProcedure) F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(loid));
|
|
|
|
|
|
|
|
pg_largeobject = heap_openr(LargeObjectRelationName, RowShareLock);
|
|
|
|
pg_lo_idx = index_openr(LargeObjectLOidPNIndex);
|
|
|
|
|
2002-05-21 01:51:44 +02:00
|
|
|
sd = index_beginscan(pg_largeobject, pg_lo_idx, SnapshotNow, 1, skey);
|
2000-10-24 03:38:44 +02:00
|
|
|
|
2002-05-21 01:51:44 +02:00
|
|
|
while ((tuple = index_getnext(sd, ForwardScanDirection)) != NULL)
|
2000-10-24 03:38:44 +02:00
|
|
|
{
|
2002-05-21 01:51:44 +02:00
|
|
|
simple_heap_delete(pg_largeobject, &tuple->t_self);
|
|
|
|
found = true;
|
2000-10-24 03:38:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
index_endscan(sd);
|
|
|
|
|
|
|
|
index_close(pg_lo_idx);
|
|
|
|
heap_close(pg_largeobject, RowShareLock);
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
elog(ERROR, "LargeObjectDrop: large object %u not found", loid);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
LargeObjectExists(Oid loid)
|
|
|
|
{
|
|
|
|
bool retval = false;
|
|
|
|
Relation pg_largeobject;
|
|
|
|
Relation pg_lo_idx;
|
2001-03-22 05:01:46 +01:00
|
|
|
ScanKeyData skey[1];
|
2000-10-24 03:38:44 +02:00
|
|
|
IndexScanDesc sd;
|
2002-05-21 01:51:44 +02:00
|
|
|
HeapTuple tuple;
|
2000-10-24 03:38:44 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* See if we can find any tuples belonging to the specified LO
|
|
|
|
*/
|
|
|
|
ScanKeyEntryInitialize(&skey[0],
|
|
|
|
(bits16) 0x0,
|
|
|
|
(AttrNumber) 1,
|
|
|
|
(RegProcedure) F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(loid));
|
|
|
|
|
|
|
|
pg_largeobject = heap_openr(LargeObjectRelationName, RowShareLock);
|
|
|
|
pg_lo_idx = index_openr(LargeObjectLOidPNIndex);
|
|
|
|
|
2002-05-21 01:51:44 +02:00
|
|
|
sd = index_beginscan(pg_largeobject, pg_lo_idx, SnapshotNow, 1, skey);
|
2000-10-24 03:38:44 +02:00
|
|
|
|
2002-05-21 01:51:44 +02:00
|
|
|
if ((tuple = index_getnext(sd, ForwardScanDirection)) != NULL)
|
|
|
|
retval = true;
|
2000-10-24 03:38:44 +02:00
|
|
|
|
|
|
|
index_endscan(sd);
|
|
|
|
|
|
|
|
index_close(pg_lo_idx);
|
|
|
|
heap_close(pg_largeobject, RowShareLock);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|