~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/tid.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * tid.c
 
4
 *        Functions for the built-in type tuple id
 
5
 *
 
6
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        $PostgreSQL: pgsql/src/backend/utils/adt/tid.c,v 1.48 2004-12-31 22:01:22 pgsql Exp $
 
12
 *
 
13
 * NOTES
 
14
 *        input routine largely stolen from boxin().
 
15
 *
 
16
 *-------------------------------------------------------------------------
 
17
 */
 
18
#include "postgres.h"
 
19
 
 
20
#include <errno.h>
 
21
#include <math.h>
 
22
#include <limits.h>
 
23
 
 
24
#include "access/heapam.h"
 
25
#include "catalog/namespace.h"
 
26
#include "catalog/pg_type.h"
 
27
#include "libpq/pqformat.h"
 
28
#include "parser/parsetree.h"
 
29
#include "utils/builtins.h"
 
30
 
 
31
 
 
32
#define DatumGetItemPointer(X)   ((ItemPointer) DatumGetPointer(X))
 
33
#define ItemPointerGetDatum(X)   PointerGetDatum(X)
 
34
#define PG_GETARG_ITEMPOINTER(n) DatumGetItemPointer(PG_GETARG_DATUM(n))
 
35
#define PG_RETURN_ITEMPOINTER(x) return ItemPointerGetDatum(x)
 
36
 
 
37
#define LDELIM                  '('
 
38
#define RDELIM                  ')'
 
39
#define DELIM                   ','
 
40
#define NTIDARGS                2
 
41
 
 
42
/* ----------------------------------------------------------------
 
43
 *              tidin
 
44
 * ----------------------------------------------------------------
 
45
 */
 
46
Datum
 
47
tidin(PG_FUNCTION_ARGS)
 
48
{
 
49
        char       *str = PG_GETARG_CSTRING(0);
 
50
        char       *p,
 
51
                           *coord[NTIDARGS];
 
52
        int                     i;
 
53
        ItemPointer result;
 
54
        BlockNumber blockNumber;
 
55
        OffsetNumber offsetNumber;
 
56
        char       *badp;
 
57
        int                     hold_offset;
 
58
 
 
59
        for (i = 0, p = str; *p && i < NTIDARGS && *p != RDELIM; p++)
 
60
                if (*p == DELIM || (*p == LDELIM && !i))
 
61
                        coord[i++] = p + 1;
 
62
 
 
63
        if (i < NTIDARGS)
 
64
                ereport(ERROR,
 
65
                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
66
                                 errmsg("invalid input syntax for type tid: \"%s\"",
 
67
                                                str)));
 
68
 
 
69
        errno = 0;
 
70
        blockNumber = strtoul(coord[0], &badp, 10);
 
71
        if (errno || *badp != DELIM)
 
72
                ereport(ERROR,
 
73
                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
74
                                 errmsg("invalid input syntax for type tid: \"%s\"",
 
75
                                                str)));
 
76
 
 
77
        hold_offset = strtol(coord[1], &badp, 10);
 
78
        if (errno || *badp != RDELIM ||
 
79
                hold_offset > USHRT_MAX || hold_offset < 0)
 
80
                ereport(ERROR,
 
81
                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
82
                                 errmsg("invalid input syntax for type tid: \"%s\"",
 
83
                                                str)));
 
84
 
 
85
        offsetNumber = hold_offset;
 
86
 
 
87
        result = (ItemPointer) palloc(sizeof(ItemPointerData));
 
88
 
 
89
        ItemPointerSet(result, blockNumber, offsetNumber);
 
90
 
 
91
        PG_RETURN_ITEMPOINTER(result);
 
92
}
 
93
 
 
94
/* ----------------------------------------------------------------
 
95
 *              tidout
 
96
 * ----------------------------------------------------------------
 
97
 */
 
98
Datum
 
99
tidout(PG_FUNCTION_ARGS)
 
100
{
 
101
        ItemPointer itemPtr = PG_GETARG_ITEMPOINTER(0);
 
102
        BlockId         blockId;
 
103
        BlockNumber blockNumber;
 
104
        OffsetNumber offsetNumber;
 
105
        char            buf[32];
 
106
 
 
107
        if (!ItemPointerIsValid(itemPtr))
 
108
                PG_RETURN_CSTRING(pstrdup("()"));
 
109
 
 
110
        blockId = &(itemPtr->ip_blkid);
 
111
        blockNumber = BlockIdGetBlockNumber(blockId);
 
112
        offsetNumber = itemPtr->ip_posid;
 
113
 
 
114
        snprintf(buf, sizeof(buf), "(%u,%u)", blockNumber, offsetNumber);
 
115
 
 
116
        PG_RETURN_CSTRING(pstrdup(buf));
 
117
}
 
118
 
 
119
/*
 
120
 *              tidrecv                 - converts external binary format to tid
 
121
 */
 
122
Datum
 
123
tidrecv(PG_FUNCTION_ARGS)
 
124
{
 
125
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
 
126
        ItemPointer result;
 
127
        BlockNumber blockNumber;
 
128
        OffsetNumber offsetNumber;
 
129
 
 
130
        blockNumber = pq_getmsgint(buf, sizeof(blockNumber));
 
131
        offsetNumber = pq_getmsgint(buf, sizeof(offsetNumber));
 
132
 
 
133
        result = (ItemPointer) palloc(sizeof(ItemPointerData));
 
134
 
 
135
        ItemPointerSet(result, blockNumber, offsetNumber);
 
136
 
 
137
        PG_RETURN_ITEMPOINTER(result);
 
138
}
 
139
 
 
140
/*
 
141
 *              tidsend                 - converts tid to binary format
 
142
 */
 
143
Datum
 
144
tidsend(PG_FUNCTION_ARGS)
 
145
{
 
146
        ItemPointer itemPtr = PG_GETARG_ITEMPOINTER(0);
 
147
        BlockId         blockId;
 
148
        BlockNumber blockNumber;
 
149
        OffsetNumber offsetNumber;
 
150
        StringInfoData buf;
 
151
 
 
152
        blockId = &(itemPtr->ip_blkid);
 
153
        blockNumber = BlockIdGetBlockNumber(blockId);
 
154
        offsetNumber = itemPtr->ip_posid;
 
155
 
 
156
        pq_begintypsend(&buf);
 
157
        pq_sendint(&buf, blockNumber, sizeof(blockNumber));
 
158
        pq_sendint(&buf, offsetNumber, sizeof(offsetNumber));
 
159
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 
160
}
 
161
 
 
162
/*****************************************************************************
 
163
 *       PUBLIC ROUTINES                                                                                                                 *
 
164
 *****************************************************************************/
 
165
 
 
166
Datum
 
167
tideq(PG_FUNCTION_ARGS)
 
168
{
 
169
        ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
 
170
        ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
 
171
 
 
172
        PG_RETURN_BOOL(BlockIdGetBlockNumber(&(arg1->ip_blkid)) ==
 
173
                                   BlockIdGetBlockNumber(&(arg2->ip_blkid)) &&
 
174
                                   arg1->ip_posid == arg2->ip_posid);
 
175
}
 
176
 
 
177
#ifdef NOT_USED
 
178
Datum
 
179
tidne(PG_FUNCTION_ARGS)
 
180
{
 
181
        ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
 
182
        ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
 
183
 
 
184
        PG_RETURN_BOOL(BlockIdGetBlockNumber(&(arg1->ip_blkid)) !=
 
185
                                   BlockIdGetBlockNumber(&(arg2->ip_blkid)) ||
 
186
                                   arg1->ip_posid != arg2->ip_posid);
 
187
}
 
188
#endif
 
189
 
 
190
/*
 
191
 *      Functions to get latest tid of a specified tuple.
 
192
 *
 
193
 *      Maybe these implementations should be moved to another place
 
194
 */
 
195
 
 
196
static ItemPointerData Current_last_tid = {{0, 0}, 0};
 
197
 
 
198
void
 
199
setLastTid(const ItemPointer tid)
 
200
{
 
201
        Current_last_tid = *tid;
 
202
}
 
203
 
 
204
/*
 
205
 *      Handle CTIDs of views.
 
206
 *              CTID should be defined in the view and it must
 
207
 *              correspond to the CTID of a base relation.
 
208
 */
 
209
static Datum
 
210
currtid_for_view(Relation viewrel, ItemPointer tid)
 
211
{
 
212
        TupleDesc       att = RelationGetDescr(viewrel);
 
213
        RuleLock   *rulelock;
 
214
        RewriteRule *rewrite;
 
215
        int                     i,
 
216
                                natts = att->natts,
 
217
                                tididx = -1;
 
218
 
 
219
        for (i = 0; i < natts; i++)
 
220
        {
 
221
                if (strcmp(NameStr(att->attrs[i]->attname), "ctid") == 0)
 
222
                {
 
223
                        if (att->attrs[i]->atttypid != TIDOID)
 
224
                                elog(ERROR, "ctid isn't of type TID");
 
225
                        tididx = i;
 
226
                        break;
 
227
                }
 
228
        }
 
229
        if (tididx < 0)
 
230
                elog(ERROR, "currtid cannot handle views with no CTID");
 
231
        rulelock = viewrel->rd_rules;
 
232
        if (!rulelock)
 
233
                elog(ERROR, "the view has no rules");
 
234
        for (i = 0; i < rulelock->numLocks; i++)
 
235
        {
 
236
                rewrite = rulelock->rules[i];
 
237
                if (rewrite->event == CMD_SELECT)
 
238
                {
 
239
                        Query      *query;
 
240
                        TargetEntry *tle;
 
241
 
 
242
                        if (list_length(rewrite->actions) != 1)
 
243
                                elog(ERROR, "only one select rule is allowed in views");
 
244
                        query = (Query *) linitial(rewrite->actions);
 
245
                        tle = get_tle_by_resno(query->targetList, tididx + 1);
 
246
                        if (tle && tle->expr && IsA(tle->expr, Var))
 
247
                        {
 
248
                                Var                *var = (Var *) tle->expr;
 
249
                                RangeTblEntry *rte;
 
250
 
 
251
                                if (var->varno > 0 && var->varno < INNER &&
 
252
                                        var->varattno == SelfItemPointerAttributeNumber)
 
253
                                {
 
254
                                        rte = rt_fetch(var->varno, query->rtable);
 
255
                                        if (rte)
 
256
                                        {
 
257
                                                heap_close(viewrel, AccessShareLock);
 
258
                                                return DirectFunctionCall2(currtid_byreloid, ObjectIdGetDatum(rte->relid), PointerGetDatum(tid));
 
259
                                        }
 
260
                                }
 
261
                        }
 
262
                        break;
 
263
                }
 
264
        }
 
265
        elog(ERROR, "currtid cannot handle this view");
 
266
        return (Datum) 0;
 
267
}
 
268
 
 
269
Datum
 
270
currtid_byreloid(PG_FUNCTION_ARGS)
 
271
{
 
272
        Oid                     reloid = PG_GETARG_OID(0);
 
273
        ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
 
274
        ItemPointer result;
 
275
        Relation        rel;
 
276
 
 
277
        result = (ItemPointer) palloc(sizeof(ItemPointerData));
 
278
        if (!reloid)
 
279
        {
 
280
                *result = Current_last_tid;
 
281
                PG_RETURN_ITEMPOINTER(result);
 
282
        }
 
283
 
 
284
        rel = heap_open(reloid, AccessShareLock);
 
285
        if (rel->rd_rel->relkind == RELKIND_VIEW)
 
286
                return currtid_for_view(rel, tid);
 
287
 
 
288
        ItemPointerCopy(tid, result);
 
289
        heap_get_latest_tid(rel, SnapshotNow, result);
 
290
 
 
291
        heap_close(rel, AccessShareLock);
 
292
 
 
293
        PG_RETURN_ITEMPOINTER(result);
 
294
}
 
295
 
 
296
Datum
 
297
currtid_byrelname(PG_FUNCTION_ARGS)
 
298
{
 
299
        text       *relname = PG_GETARG_TEXT_P(0);
 
300
        ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
 
301
        ItemPointer result;
 
302
        RangeVar   *relrv;
 
303
        Relation        rel;
 
304
 
 
305
        relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
 
306
                                                                                                   "currtid_byrelname"));
 
307
        rel = heap_openrv(relrv, AccessShareLock);
 
308
        if (rel->rd_rel->relkind == RELKIND_VIEW)
 
309
                return currtid_for_view(rel, tid);
 
310
 
 
311
        result = (ItemPointer) palloc(sizeof(ItemPointerData));
 
312
        ItemPointerCopy(tid, result);
 
313
 
 
314
        heap_get_latest_tid(rel, SnapshotNow, result);
 
315
 
 
316
        heap_close(rel, AccessShareLock);
 
317
 
 
318
        PG_RETURN_ITEMPOINTER(result);
 
319
}