2
* PostgreSQL type definitions for managed LargeObjects.
4
* $PostgreSQL: pgsql/contrib/lo/lo.c,v 1.14 2003-11-29 19:51:35 pgsql Exp $
10
/* Required for largeobjects */
11
#include "libpq/libpq-fs.h"
12
#include "libpq/be-fsstubs.h"
14
/* Required for SPI */
15
#include "executor/spi.h"
17
/* Required for triggers */
18
#include "commands/trigger.h"
21
#define atooid(x) ((Oid) strtoul((x), NULL, 10))
25
* This is the internal storage format for managed large objects
32
* Various forward declarations:
35
Blob *lo_in(char *str); /* Create from String */
36
char *lo_out(Blob * addr); /* Output oid as String */
37
Oid lo_oid(Blob * addr); /* Return oid as an oid */
38
Blob *lo(Oid oid); /* Return Blob based on oid */
39
Datum lo_manage(PG_FUNCTION_ARGS); /* Trigger handler */
42
* This creates a large object, and sets its OID to the value in the
45
* If the string is empty, then a new LargeObject is created, and its oid
46
* is placed in the resulting lo.
57
count = sscanf(str, "%u", &oid);
61
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
62
errmsg("error in parsing \"%s\"", str)));
64
if (oid == InvalidOid)
66
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
67
errmsg("illegal oid: \"%s\"", str)));
72
* There is no Oid passed, so create a new one
74
oid = DatumGetObjectId(DirectFunctionCall1(lo_creat,
75
Int32GetDatum(INV_READ | INV_WRITE)));
76
if (oid == InvalidOid)
78
elog(ERROR, "InvalidOid returned from lo_creat");
81
result = (Blob *) palloc(sizeof(Blob));
89
* This simply outputs the Oid of the Blob as a string.
99
result = (char *) palloc(32);
100
snprintf(result, 32, "%u", *addr);
105
* This function converts Blob to oid.
107
* eg: select lo_export(raster::oid,'/path/file') from table;
115
return (Oid) (*addr);
119
* This function is used so we can convert oid's to lo's
121
* ie: insert into table values(lo_import('/path/file')::lo);
127
Blob *result = (Blob *) palloc(sizeof(Blob));
134
* This handles the trigger that protects us from orphaned large objects
136
PG_FUNCTION_INFO_V1(lo_manage);
139
lo_manage(PG_FUNCTION_ARGS)
141
TriggerData *trigdata = (TriggerData *) fcinfo->context;
142
int attnum; /* attribute number to monitor */
143
char **args; /* Args containing attr name */
144
TupleDesc tupdesc; /* Tuple Descriptor */
145
HeapTuple rettuple; /* Tuple to be returned */
146
bool isdelete; /* are we deleting? */
147
HeapTuple newtuple = NULL; /* The new value for tuple */
148
HeapTuple trigtuple; /* The original value of tuple */
150
if (!CALLED_AS_TRIGGER(fcinfo))
152
elog(ERROR, "not fired by trigger manager");
155
* Fetch some values from trigdata
157
newtuple = trigdata->tg_newtuple;
158
trigtuple = trigdata->tg_trigtuple;
159
tupdesc = trigdata->tg_relation->rd_att;
160
args = trigdata->tg_trigger->tgargs;
162
/* tuple to return to Executor */
163
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
166
rettuple = trigtuple;
168
/* Are we deleting the row? */
169
isdelete = TRIGGER_FIRED_BY_DELETE(trigdata->tg_event);
171
/* Get the column were interested in */
172
attnum = SPI_fnumber(tupdesc, args[0]);
177
* Here, if the value of the monitored attribute changes, then the large
178
* object associated with the original value is unlinked.
180
if (newtuple != NULL)
182
char *orig = SPI_getvalue(trigtuple, tupdesc, attnum);
183
char *newv = SPI_getvalue(newtuple, tupdesc, attnum);
185
if (orig != NULL && (newv == NULL || strcmp(orig, newv)))
186
DirectFunctionCall1(lo_unlink,
187
ObjectIdGetDatum(atooid(orig)));
196
* Handle deleting of rows
198
* Here, we unlink the large object associated with the managed attribute
203
char *orig = SPI_getvalue(trigtuple, tupdesc, attnum);
207
DirectFunctionCall1(lo_unlink,
208
ObjectIdGetDatum(atooid(orig)));
214
return PointerGetDatum(rettuple);