~ubuntu-branches/debian/sid/postgresql-9.3/sid

« back to all changes in this revision

Viewing changes to contrib/lo/lo.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2013-05-08 05:39:52 UTC
  • Revision ID: package-import@ubuntu.com-20130508053952-1j7uilp7mjtrvq8q
Tags: upstream-9.3~beta1
ImportĀ upstreamĀ versionĀ 9.3~beta1

Show diffs side-by-side

added added

removed removed

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