1
/*-------------------------------------------------------------------------
4
* Functions for the built-in type tuple id
6
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7
* Portions Copyright (c) 1994, Regents of the University of California
11
* $PostgreSQL: pgsql/src/backend/utils/adt/tid.c,v 1.48 2004-12-31 22:01:22 pgsql Exp $
14
* input routine largely stolen from boxin().
16
*-------------------------------------------------------------------------
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"
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)
42
/* ----------------------------------------------------------------
44
* ----------------------------------------------------------------
47
tidin(PG_FUNCTION_ARGS)
49
char *str = PG_GETARG_CSTRING(0);
54
BlockNumber blockNumber;
55
OffsetNumber offsetNumber;
59
for (i = 0, p = str; *p && i < NTIDARGS && *p != RDELIM; p++)
60
if (*p == DELIM || (*p == LDELIM && !i))
65
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
66
errmsg("invalid input syntax for type tid: \"%s\"",
70
blockNumber = strtoul(coord[0], &badp, 10);
71
if (errno || *badp != DELIM)
73
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
74
errmsg("invalid input syntax for type tid: \"%s\"",
77
hold_offset = strtol(coord[1], &badp, 10);
78
if (errno || *badp != RDELIM ||
79
hold_offset > USHRT_MAX || hold_offset < 0)
81
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
82
errmsg("invalid input syntax for type tid: \"%s\"",
85
offsetNumber = hold_offset;
87
result = (ItemPointer) palloc(sizeof(ItemPointerData));
89
ItemPointerSet(result, blockNumber, offsetNumber);
91
PG_RETURN_ITEMPOINTER(result);
94
/* ----------------------------------------------------------------
96
* ----------------------------------------------------------------
99
tidout(PG_FUNCTION_ARGS)
101
ItemPointer itemPtr = PG_GETARG_ITEMPOINTER(0);
103
BlockNumber blockNumber;
104
OffsetNumber offsetNumber;
107
if (!ItemPointerIsValid(itemPtr))
108
PG_RETURN_CSTRING(pstrdup("()"));
110
blockId = &(itemPtr->ip_blkid);
111
blockNumber = BlockIdGetBlockNumber(blockId);
112
offsetNumber = itemPtr->ip_posid;
114
snprintf(buf, sizeof(buf), "(%u,%u)", blockNumber, offsetNumber);
116
PG_RETURN_CSTRING(pstrdup(buf));
120
* tidrecv - converts external binary format to tid
123
tidrecv(PG_FUNCTION_ARGS)
125
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
127
BlockNumber blockNumber;
128
OffsetNumber offsetNumber;
130
blockNumber = pq_getmsgint(buf, sizeof(blockNumber));
131
offsetNumber = pq_getmsgint(buf, sizeof(offsetNumber));
133
result = (ItemPointer) palloc(sizeof(ItemPointerData));
135
ItemPointerSet(result, blockNumber, offsetNumber);
137
PG_RETURN_ITEMPOINTER(result);
141
* tidsend - converts tid to binary format
144
tidsend(PG_FUNCTION_ARGS)
146
ItemPointer itemPtr = PG_GETARG_ITEMPOINTER(0);
148
BlockNumber blockNumber;
149
OffsetNumber offsetNumber;
152
blockId = &(itemPtr->ip_blkid);
153
blockNumber = BlockIdGetBlockNumber(blockId);
154
offsetNumber = itemPtr->ip_posid;
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));
162
/*****************************************************************************
164
*****************************************************************************/
167
tideq(PG_FUNCTION_ARGS)
169
ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
170
ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
172
PG_RETURN_BOOL(BlockIdGetBlockNumber(&(arg1->ip_blkid)) ==
173
BlockIdGetBlockNumber(&(arg2->ip_blkid)) &&
174
arg1->ip_posid == arg2->ip_posid);
179
tidne(PG_FUNCTION_ARGS)
181
ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
182
ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
184
PG_RETURN_BOOL(BlockIdGetBlockNumber(&(arg1->ip_blkid)) !=
185
BlockIdGetBlockNumber(&(arg2->ip_blkid)) ||
186
arg1->ip_posid != arg2->ip_posid);
191
* Functions to get latest tid of a specified tuple.
193
* Maybe these implementations should be moved to another place
196
static ItemPointerData Current_last_tid = {{0, 0}, 0};
199
setLastTid(const ItemPointer tid)
201
Current_last_tid = *tid;
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.
210
currtid_for_view(Relation viewrel, ItemPointer tid)
212
TupleDesc att = RelationGetDescr(viewrel);
214
RewriteRule *rewrite;
219
for (i = 0; i < natts; i++)
221
if (strcmp(NameStr(att->attrs[i]->attname), "ctid") == 0)
223
if (att->attrs[i]->atttypid != TIDOID)
224
elog(ERROR, "ctid isn't of type TID");
230
elog(ERROR, "currtid cannot handle views with no CTID");
231
rulelock = viewrel->rd_rules;
233
elog(ERROR, "the view has no rules");
234
for (i = 0; i < rulelock->numLocks; i++)
236
rewrite = rulelock->rules[i];
237
if (rewrite->event == CMD_SELECT)
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))
248
Var *var = (Var *) tle->expr;
251
if (var->varno > 0 && var->varno < INNER &&
252
var->varattno == SelfItemPointerAttributeNumber)
254
rte = rt_fetch(var->varno, query->rtable);
257
heap_close(viewrel, AccessShareLock);
258
return DirectFunctionCall2(currtid_byreloid, ObjectIdGetDatum(rte->relid), PointerGetDatum(tid));
265
elog(ERROR, "currtid cannot handle this view");
270
currtid_byreloid(PG_FUNCTION_ARGS)
272
Oid reloid = PG_GETARG_OID(0);
273
ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
277
result = (ItemPointer) palloc(sizeof(ItemPointerData));
280
*result = Current_last_tid;
281
PG_RETURN_ITEMPOINTER(result);
284
rel = heap_open(reloid, AccessShareLock);
285
if (rel->rd_rel->relkind == RELKIND_VIEW)
286
return currtid_for_view(rel, tid);
288
ItemPointerCopy(tid, result);
289
heap_get_latest_tid(rel, SnapshotNow, result);
291
heap_close(rel, AccessShareLock);
293
PG_RETURN_ITEMPOINTER(result);
297
currtid_byrelname(PG_FUNCTION_ARGS)
299
text *relname = PG_GETARG_TEXT_P(0);
300
ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
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);
311
result = (ItemPointer) palloc(sizeof(ItemPointerData));
312
ItemPointerCopy(tid, result);
314
heap_get_latest_tid(rel, SnapshotNow, result);
316
heap_close(rel, AccessShareLock);
318
PG_RETURN_ITEMPOINTER(result);