postgresql/src/backend/catalog/pg_largeobject.c
Tom Lane a2a8c7a662 Support hex-string input and output for type BYTEA.
Both hex format and the traditional "escape" format are automatically
handled on input.  The output format is selected by the new GUC variable
bytea_output.

As committed, bytea_output defaults to HEX, which is an *incompatible
change*.  We will keep it this way for awhile for testing purposes, but
should consider whether to switch to the more backwards-compatible
default of ESCAPE before 8.5 is released.

Peter Eisentraut
2009-08-04 16:08:37 +00:00

140 lines
3.1 KiB
C

/*-------------------------------------------------------------------------
*
* pg_largeobject.c
* routines to support manipulation of the pg_largeobject relation
*
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_largeobject.c,v 1.33 2009/08/04 16:08:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/indexing.h"
#include "catalog/pg_largeobject.h"
#include "utils/bytea.h"
#include "utils/fmgroids.h"
#include "utils/rel.h"
#include "utils/tqual.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.
*/
void
LargeObjectCreate(Oid loid)
{
Relation pg_largeobject;
HeapTuple ntup;
Datum values[Natts_pg_largeobject];
bool nulls[Natts_pg_largeobject];
int i;
pg_largeobject = heap_open(LargeObjectRelationId, RowExclusiveLock);
/*
* Form new tuple
*/
for (i = 0; i < Natts_pg_largeobject; i++)
{
values[i] = (Datum) NULL;
nulls[i] = false;
}
i = 0;
values[i++] = ObjectIdGetDatum(loid);
values[i++] = Int32GetDatum(0);
values[i++] = DirectFunctionCall1(byteain,
CStringGetDatum(""));
ntup = heap_form_tuple(pg_largeobject->rd_att, values, nulls);
/*
* Insert it
*/
simple_heap_insert(pg_largeobject, ntup);
/* Update indexes */
CatalogUpdateIndexes(pg_largeobject, ntup);
heap_close(pg_largeobject, RowExclusiveLock);
heap_freetuple(ntup);
}
void
LargeObjectDrop(Oid loid)
{
bool found = false;
Relation pg_largeobject;
ScanKeyData skey[1];
SysScanDesc sd;
HeapTuple tuple;
ScanKeyInit(&skey[0],
Anum_pg_largeobject_loid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(loid));
pg_largeobject = heap_open(LargeObjectRelationId, RowExclusiveLock);
sd = systable_beginscan(pg_largeobject, LargeObjectLOidPNIndexId, true,
SnapshotNow, 1, skey);
while ((tuple = systable_getnext(sd)) != NULL)
{
simple_heap_delete(pg_largeobject, &tuple->t_self);
found = true;
}
systable_endscan(sd);
heap_close(pg_largeobject, RowExclusiveLock);
if (!found)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("large object %u does not exist", loid)));
}
bool
LargeObjectExists(Oid loid)
{
bool retval = false;
Relation pg_largeobject;
ScanKeyData skey[1];
SysScanDesc sd;
/*
* See if we can find any tuples belonging to the specified LO
*/
ScanKeyInit(&skey[0],
Anum_pg_largeobject_loid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(loid));
pg_largeobject = heap_open(LargeObjectRelationId, AccessShareLock);
sd = systable_beginscan(pg_largeobject, LargeObjectLOidPNIndexId, true,
SnapshotNow, 1, skey);
if (systable_getnext(sd) != NULL)
retval = true;
systable_endscan(sd);
heap_close(pg_largeobject, AccessShareLock);
return retval;
}