PostgreSQL Source Code git master
Loading...
Searching...
No Matches
tid.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * tid.c
4 * Functions for the built-in type tuple id
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/utils/adt/tid.c
12 *
13 * NOTES
14 * input routine largely stolen from boxin().
15 *
16 *-------------------------------------------------------------------------
17 */
18#include "postgres.h"
19
20#include <limits.h>
21
22#include "access/sysattr.h"
23#include "access/table.h"
24#include "access/tableam.h"
25#include "catalog/namespace.h"
26#include "catalog/pg_type.h"
27#include "common/hashfn.h"
28#include "libpq/pqformat.h"
29#include "miscadmin.h"
30#include "parser/parsetree.h"
31#include "utils/acl.h"
32#include "utils/fmgrprotos.h"
33#include "utils/lsyscache.h"
34#include "utils/rel.h"
35#include "utils/snapmgr.h"
36#include "utils/varlena.h"
37
38
39#define LDELIM '('
40#define RDELIM ')'
41#define DELIM ','
42#define NTIDARGS 2
43
45
46/* ----------------------------------------------------------------
47 * tidin
48 * ----------------------------------------------------------------
49 */
52{
53 char *str = PG_GETARG_CSTRING(0);
54 Node *escontext = fcinfo->context;
55 char *p,
57 int i;
58 ItemPointer result;
61 char *badp;
62 unsigned long cvt;
63
64 for (i = 0, p = str; *p && i < NTIDARGS && *p != RDELIM; p++)
65 if (*p == DELIM || (*p == LDELIM && i == 0))
66 coord[i++] = p + 1;
67
68 if (i < NTIDARGS)
69 ereturn(escontext, (Datum) 0,
71 errmsg("invalid input syntax for type %s: \"%s\"",
72 "tid", str)));
73
74 errno = 0;
75 cvt = strtoul(coord[0], &badp, 10);
76 if (errno || *badp != DELIM)
77 ereturn(escontext, (Datum) 0,
79 errmsg("invalid input syntax for type %s: \"%s\"",
80 "tid", str)));
82
83 /*
84 * Cope with possibility that unsigned long is wider than BlockNumber, in
85 * which case strtoul will not raise an error for some values that are out
86 * of the range of BlockNumber. (See similar code in uint32in_subr().)
87 */
88#if SIZEOF_LONG > 4
89 if (cvt != (unsigned long) blockNumber &&
90 cvt != (unsigned long) ((int32) blockNumber))
91 ereturn(escontext, (Datum) 0,
93 errmsg("invalid input syntax for type %s: \"%s\"",
94 "tid", str)));
95#endif
96
97 cvt = strtoul(coord[1], &badp, 10);
98 if (errno || *badp != RDELIM ||
99 cvt > USHRT_MAX)
100 ereturn(escontext, (Datum) 0,
102 errmsg("invalid input syntax for type %s: \"%s\"",
103 "tid", str)));
105
107
109
110 PG_RETURN_ITEMPOINTER(result);
111}
112
113/* ----------------------------------------------------------------
114 * tidout
115 * ----------------------------------------------------------------
116 */
117Datum
119{
123 char buf[32];
124
127
128 /* Perhaps someday we should output this as a record. */
129 snprintf(buf, sizeof(buf), "(%u,%u)", blockNumber, offsetNumber);
130
132}
133
134/*
135 * tidrecv - converts external binary format to tid
136 */
137Datum
154
155/*
156 * tidsend - converts tid to binary format
157 */
158Datum
169
170/*****************************************************************************
171 * PUBLIC ROUTINES *
172 *****************************************************************************/
173
174Datum
182
183Datum
191
192Datum
200
201Datum
209
210Datum
218
219Datum
227
228Datum
236
237Datum
245
246Datum
254
255Datum
257{
259
260 /*
261 * While you'll probably have a lot of trouble with a compiler that
262 * insists on appending pad space to struct ItemPointerData, we can at
263 * least make this code work, by not using sizeof(ItemPointerData).
264 * Instead rely on knowing the sizes of the component fields.
265 */
266 return hash_any((unsigned char *) key,
267 sizeof(BlockIdData) + sizeof(OffsetNumber));
268}
269
270Datum
272{
274 uint64 seed = PG_GETARG_INT64(1);
275
276 /* As above */
277 return hash_any_extended((unsigned char *) key,
278 sizeof(BlockIdData) + sizeof(OffsetNumber),
279 seed);
280}
281
282
283/*
284 * Functions to get latest tid of a specified tuple.
285 *
286 * Maybe these implementations should be moved to another place
287 */
288
289/*
290 * Utility wrapper for current CTID functions.
291 * Returns the latest version of a tuple pointing at "tid" for
292 * relation "rel".
293 */
294static ItemPointer
296{
297 ItemPointer result;
299 Snapshot snapshot;
300 TableScanDesc scan;
301
303
305 ACL_SELECT);
306 if (aclresult != ACLCHECK_OK)
309
310 if (rel->rd_rel->relkind == RELKIND_VIEW)
311 return currtid_for_view(rel, tid);
312
313 if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
316 errmsg("cannot look at latest visible tid for relation \"%s.%s\"",
319
320 ItemPointerCopy(tid, result);
321
323 scan = table_beginscan_tid(rel, snapshot);
324 table_tuple_get_latest_tid(scan, result);
325 table_endscan(scan);
326 UnregisterSnapshot(snapshot);
327
328 return result;
329}
330
331/*
332 * Handle CTIDs of views.
333 * CTID should be defined in the view and it must
334 * correspond to the CTID of a base relation.
335 */
336static ItemPointer
338{
341 RewriteRule *rewrite;
342 int i,
343 natts = att->natts,
344 tididx = -1;
345
346 for (i = 0; i < natts; i++)
347 {
349
350 if (strcmp(NameStr(attr->attname), "ctid") == 0)
351 {
352 if (attr->atttypid != TIDOID)
355 errmsg("ctid isn't of type TID"));
356 tididx = i;
357 break;
358 }
359 }
360 if (tididx < 0)
363 errmsg("currtid cannot handle views with no CTID"));
364 rulelock = viewrel->rd_rules;
365 if (!rulelock)
368 errmsg("the view has no rules"));
369 for (i = 0; i < rulelock->numLocks; i++)
370 {
371 rewrite = rulelock->rules[i];
372 if (rewrite->event == CMD_SELECT)
373 {
374 Query *query;
376
377 if (list_length(rewrite->actions) != 1)
380 errmsg("only one select rule is allowed in views"));
381 query = (Query *) linitial(rewrite->actions);
382 tle = get_tle_by_resno(query->targetList, tididx + 1);
383 if (tle && tle->expr && IsA(tle->expr, Var))
384 {
385 Var *var = (Var *) tle->expr;
387
388 if (!IS_SPECIAL_VARNO(var->varno) &&
390 {
391 rte = rt_fetch(var->varno, query->rtable);
392 if (rte)
393 {
394 ItemPointer result;
395 Relation rel;
396
397 rel = table_open(rte->relid, AccessShareLock);
398 result = currtid_internal(rel, tid);
400 return result;
401 }
402 }
403 }
404 break;
405 }
406 }
407 elog(ERROR, "currtid cannot handle this view");
408 return NULL;
409}
410
411/*
412 * currtid_byrelname
413 * Get the latest tuple version of the tuple pointing at a CTID, for a
414 * given relation name.
415 */
416Datum
418{
421 ItemPointer result;
423 Relation rel;
424
427
428 /* grab the latest tuple version associated to this CTID */
429 result = currtid_internal(rel, tid);
430
432
433 PG_RETURN_ITEMPOINTER(result);
434}
AclResult
Definition acl.h:182
@ ACLCHECK_OK
Definition acl.h:183
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2654
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4039
uint32 BlockNumber
Definition block.h:31
#define NameStr(name)
Definition c.h:765
int32_t int32
Definition c.h:542
uint64_t uint64
Definition c.h:547
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ereturn(context, dummy_value,...)
Definition elog.h:278
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
#define palloc_object(type)
Definition fe_memutils.h:74
#define PG_GETARG_TEXT_PP(n)
Definition fmgr.h:310
#define PG_RETURN_BYTEA_P(x)
Definition fmgr.h:373
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_RETURN_CSTRING(x)
Definition fmgr.h:364
#define PG_GETARG_CSTRING(n)
Definition fmgr.h:278
#define PG_GETARG_INT64(n)
Definition fmgr.h:284
#define PG_RETURN_INT32(x)
Definition fmgr.h:355
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition hashfn.h:37
static Datum hash_any(const unsigned char *k, int keylen)
Definition hashfn.h:31
const char * str
int i
Definition isn.c:77
int32 ItemPointerCompare(const ItemPointerData *arg1, const ItemPointerData *arg2)
Definition itemptr.c:51
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
Definition itemptr.h:135
#define PG_RETURN_ITEMPOINTER(x)
Definition itemptr.h:243
static OffsetNumber ItemPointerGetOffsetNumberNoCheck(const ItemPointerData *pointer)
Definition itemptr.h:114
#define PG_GETARG_ITEMPOINTER(n)
Definition itemptr.h:242
static BlockNumber ItemPointerGetBlockNumberNoCheck(const ItemPointerData *pointer)
Definition itemptr.h:93
ItemPointerData * ItemPointer
Definition itemptr.h:49
static void ItemPointerCopy(const ItemPointerData *fromPointer, ItemPointerData *toPointer)
Definition itemptr.h:172
#define AccessShareLock
Definition lockdefs.h:36
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3516
char * pstrdup(const char *in)
Definition mcxt.c:1781
Oid GetUserId(void)
Definition miscinit.c:469
RangeVar * makeRangeVarFromNameList(const List *names)
Definition namespace.c:3624
#define IsA(nodeptr, _type_)
Definition nodes.h:164
@ CMD_SELECT
Definition nodes.h:275
ObjectType get_relkind_objtype(char relkind)
uint16 OffsetNumber
Definition off.h:24
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define ACL_SELECT
Definition parsenodes.h:77
#define rt_fetch(rangetable_index, rangetable)
Definition parsetree.h:31
FormData_pg_attribute * Form_pg_attribute
NameData relname
Definition pg_class.h:38
static int list_length(const List *l)
Definition pg_list.h:152
#define linitial(l)
Definition pg_list.h:178
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:260
uint64_t Datum
Definition postgres.h:70
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition pqformat.c:414
void pq_begintypsend(StringInfo buf)
Definition pqformat.c:325
bytea * pq_endtypsend(StringInfo buf)
Definition pqformat.c:345
static void pq_sendint32(StringInfo buf, uint32 i)
Definition pqformat.h:144
static void pq_sendint16(StringInfo buf, uint16 i)
Definition pqformat.h:136
static int fb(int x)
#define IS_SPECIAL_VARNO(varno)
Definition primnodes.h:247
#define RelationGetRelid(relation)
Definition rel.h:514
#define RelationGetDescr(relation)
Definition rel.h:540
#define RelationGetRelationName(relation)
Definition rel.h:548
#define RelationGetNamespace(relation)
Definition rel.h:555
Snapshot GetLatestSnapshot(void)
Definition snapmgr.c:354
void UnregisterSnapshot(Snapshot snapshot)
Definition snapmgr.c:866
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition snapmgr.c:824
struct StringInfoData * StringInfo
Definition string.h:15
Definition nodes.h:135
List * rtable
Definition parsenodes.h:175
List * targetList
Definition parsenodes.h:198
Form_pg_class rd_rel
Definition rel.h:111
CmdType event
Definition prs2lock.h:27
List * actions
Definition prs2lock.h:29
AttrNumber varattno
Definition primnodes.h:274
int varno
Definition primnodes.h:269
Definition c.h:706
#define SelfItemPointerAttributeNumber
Definition sysattr.h:21
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition table.c:83
void table_tuple_get_latest_tid(TableScanDesc scan, ItemPointer tid)
Definition tableam.c:267
static void table_endscan(TableScanDesc scan)
Definition tableam.h:985
static TableScanDesc table_beginscan_tid(Relation rel, Snapshot snapshot)
Definition tableam.h:961
Datum tidge(PG_FUNCTION_ARGS)
Definition tid.c:220
#define DELIM
Definition tid.c:41
Datum bttidcmp(PG_FUNCTION_ARGS)
Definition tid.c:229
Datum currtid_byrelname(PG_FUNCTION_ARGS)
Definition tid.c:417
static ItemPointer currtid_internal(Relation rel, const ItemPointerData *tid)
Definition tid.c:295
Datum hashtid(PG_FUNCTION_ARGS)
Definition tid.c:256
Datum tidlarger(PG_FUNCTION_ARGS)
Definition tid.c:238
#define NTIDARGS
Definition tid.c:42
Datum hashtidextended(PG_FUNCTION_ARGS)
Definition tid.c:271
Datum tideq(PG_FUNCTION_ARGS)
Definition tid.c:175
Datum tidgt(PG_FUNCTION_ARGS)
Definition tid.c:211
Datum tidin(PG_FUNCTION_ARGS)
Definition tid.c:51
Datum tidle(PG_FUNCTION_ARGS)
Definition tid.c:202
#define RDELIM
Definition tid.c:40
Datum tidsmaller(PG_FUNCTION_ARGS)
Definition tid.c:247
Datum tidne(PG_FUNCTION_ARGS)
Definition tid.c:184
Datum tidrecv(PG_FUNCTION_ARGS)
Definition tid.c:138
Datum tidout(PG_FUNCTION_ARGS)
Definition tid.c:118
Datum tidsend(PG_FUNCTION_ARGS)
Definition tid.c:159
Datum tidlt(PG_FUNCTION_ARGS)
Definition tid.c:193
static ItemPointer currtid_for_view(Relation viewrel, const ItemPointerData *tid)
Definition tid.c:337
#define LDELIM
Definition tid.c:39
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:160
List * textToQualifiedNameList(text *textval)
Definition varlena.c:2672