OSDN Git Service

Cleanup the contrib/lo module: there is no need anymore to implement
[pg-rex/syncrep.git] / contrib / lo / lo.c
1 /*
2  *      PostgreSQL definitions for managed Large Objects.
3  *
4  *      $PostgreSQL: pgsql/contrib/lo/lo.c,v 1.15 2005/06/23 00:06:37 tgl Exp $
5  *
6  */
7
8 #include "postgres.h"
9
10 /* Required for largeobjects */
11 #include "libpq/libpq-fs.h"
12 #include "libpq/be-fsstubs.h"
13
14 /* Required for SPI */
15 #include "executor/spi.h"
16
17 /* Required for triggers */
18 #include "commands/trigger.h"
19
20
21 #define atooid(x)  ((Oid) strtoul((x), NULL, 10))
22
23
24 /* forward declarations */
25 Datum           lo_manage(PG_FUNCTION_ARGS);
26
27
28 /*
29  * This is the trigger that protects us from orphaned large objects
30  */
31 PG_FUNCTION_INFO_V1(lo_manage);
32
33 Datum
34 lo_manage(PG_FUNCTION_ARGS)
35 {
36         TriggerData *trigdata = (TriggerData *) fcinfo->context;
37         int                     attnum;                 /* attribute number to monitor  */
38         char      **args;                       /* Args containing attr name    */
39         TupleDesc       tupdesc;                /* Tuple Descriptor                             */
40         HeapTuple       rettuple;               /* Tuple to be returned                 */
41         bool            isdelete;               /* are we deleting?                             */
42         HeapTuple       newtuple;               /* The new value for tuple              */
43         HeapTuple       trigtuple;              /* The original value of tuple  */
44
45         if (!CALLED_AS_TRIGGER(fcinfo))         /* internal error */
46                 elog(ERROR, "not fired by trigger manager");
47
48         /*
49          * Fetch some values from trigdata
50          */
51         newtuple = trigdata->tg_newtuple;
52         trigtuple = trigdata->tg_trigtuple;
53         tupdesc = trigdata->tg_relation->rd_att;
54         args = trigdata->tg_trigger->tgargs;
55
56         /* tuple to return to Executor */
57         if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
58                 rettuple = newtuple;
59         else
60                 rettuple = trigtuple;
61
62         /* Are we deleting the row? */
63         isdelete = TRIGGER_FIRED_BY_DELETE(trigdata->tg_event);
64
65         /* Get the column we're interested in */
66         attnum = SPI_fnumber(tupdesc, args[0]);
67
68         if (attnum <= 0)
69                 elog(ERROR, "column \"%s\" does not exist", args[0]);
70
71         /*
72          * Handle updates
73          *
74          * Here, if the value of the monitored attribute changes, then the large
75          * object associated with the original value is unlinked.
76          */
77         if (newtuple != NULL)
78         {
79                 char       *orig = SPI_getvalue(trigtuple, tupdesc, attnum);
80                 char       *newv = SPI_getvalue(newtuple, tupdesc, attnum);
81
82                 if (orig != NULL && (newv == NULL || strcmp(orig, newv) != 0))
83                         DirectFunctionCall1(lo_unlink,
84                                                                 ObjectIdGetDatum(atooid(orig)));
85
86                 if (newv)
87                         pfree(newv);
88                 if (orig)
89                         pfree(orig);
90         }
91
92         /*
93          * Handle deleting of rows
94          *
95          * Here, we unlink the large object associated with the managed attribute
96          */
97         if (isdelete)
98         {
99                 char       *orig = SPI_getvalue(trigtuple, tupdesc, attnum);
100
101                 if (orig != NULL)
102                 {
103                         DirectFunctionCall1(lo_unlink,
104                                                                 ObjectIdGetDatum(atooid(orig)));
105
106                         pfree(orig);
107                 }
108         }
109
110         return PointerGetDatum(rettuple);
111 }