~ubuntu-branches/ubuntu/hardy/postgresql-8.4/hardy-backports

« back to all changes in this revision

Viewing changes to contrib/lo/lo.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

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