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;
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
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 * Extract the block number from a TID
284 *
285 * Returns int8 because BlockNumber is uint32, which exceeds the range of int4.
286 */
287Datum
289{
291
292 /* need to use NoCheck, as tidin allows InvalidBlockNumber */
294}
295
296/*
297 * Extract the offset number from a TID
298 *
299 * Returns int4 because OffsetNumber is uint16, which exceeds the range of
300 * int2.
301 */
302Datum
304{
306
307 /* need to use NoCheck, as tidin allows InvalidOffsetNumber */
309}
310
311
312/*
313 * Functions to get latest tid of a specified tuple.
314 *
315 * Maybe these implementations should be moved to another place
316 */
317
318/*
319 * Utility wrapper for current CTID functions.
320 * Returns the latest version of a tuple pointing at "tid" for
321 * relation "rel".
322 */
323static ItemPointer
325{
328 Snapshot snapshot;
329 TableScanDesc scan;
330
332
334 ACL_SELECT);
335 if (aclresult != ACLCHECK_OK)
338
339 if (rel->rd_rel->relkind == RELKIND_VIEW)
340 return currtid_for_view(rel, tid);
341
342 if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
345 errmsg("cannot look at latest visible tid for relation \"%s.%s\"",
348
350
352 scan = table_beginscan_tid(rel, snapshot);
354 table_endscan(scan);
355 UnregisterSnapshot(snapshot);
356
357 return result;
358}
359
360/*
361 * Handle CTIDs of views.
362 * CTID should be defined in the view and it must
363 * correspond to the CTID of a base relation.
364 */
365static ItemPointer
367{
370 RewriteRule *rewrite;
371 int i,
372 natts = att->natts,
373 tididx = -1;
374
375 for (i = 0; i < natts; i++)
376 {
377 Form_pg_attribute attr = TupleDescAttr(att, i);
378
379 if (strcmp(NameStr(attr->attname), "ctid") == 0)
380 {
381 if (attr->atttypid != TIDOID)
384 errmsg("ctid isn't of type TID"));
385 tididx = i;
386 break;
387 }
388 }
389 if (tididx < 0)
392 errmsg("currtid cannot handle views with no CTID"));
393 rulelock = viewrel->rd_rules;
394 if (!rulelock)
397 errmsg("the view has no rules"));
398 for (i = 0; i < rulelock->numLocks; i++)
399 {
400 rewrite = rulelock->rules[i];
401 if (rewrite->event == CMD_SELECT)
402 {
403 Query *query;
405
406 if (list_length(rewrite->actions) != 1)
409 errmsg("only one select rule is allowed in views"));
410 query = (Query *) linitial(rewrite->actions);
411 tle = get_tle_by_resno(query->targetList, tididx + 1);
412 if (tle && tle->expr && IsA(tle->expr, Var))
413 {
414 Var *var = (Var *) tle->expr;
416
417 if (!IS_SPECIAL_VARNO(var->varno) &&
419 {
420 rte = rt_fetch(var->varno, query->rtable);
421 if (rte)
422 {
424 Relation rel;
425
426 rel = table_open(rte->relid, AccessShareLock);
427 result = currtid_internal(rel, tid);
429 return result;
430 }
431 }
432 }
433 break;
434 }
435 }
436 elog(ERROR, "currtid cannot handle this view");
437 return NULL;
438}
439
440/*
441 * currtid_byrelname
442 * Get the latest tuple version of the tuple pointing at a CTID, for a
443 * given relation name.
444 */
445Datum
447{
452 Relation rel;
453
456
457 /* grab the latest tuple version associated to this CTID */
458 result = currtid_internal(rel, tid);
459
461
463}
AclResult
Definition acl.h:183
@ ACLCHECK_OK
Definition acl.h:184
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4082
uint32 BlockNumber
Definition block.h:31
#define NameStr(name)
Definition c.h:835
int64_t int64
Definition c.h:621
int32_t int32
Definition c.h:620
uint64_t uint64
Definition c.h:625
uint32 result
int errcode(int sqlerrcode)
Definition elog.c:874
#define ereturn(context, dummy_value,...)
Definition elog.h:280
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
#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_RETURN_INT64(x)
Definition fmgr.h:370
#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:3588
char * pstrdup(const char *in)
Definition mcxt.c:1781
Oid GetUserId(void)
Definition miscinit.c:470
RangeVar * makeRangeVarFromNameList(const List *names)
Definition namespace.c:3626
#define IsA(nodeptr, _type_)
Definition nodes.h:164
@ CMD_SELECT
Definition nodes.h:275
static char * errmsg
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:40
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:248
#define RelationGetRelid(relation)
Definition rel.h:516
#define RelationGetDescr(relation)
Definition rel.h:542
#define RelationGetRelationName(relation)
Definition rel.h:550
#define RelationGetNamespace(relation)
Definition rel.h:557
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:178
List * targetList
Definition parsenodes.h:201
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:275
int varno
Definition primnodes.h:270
Definition c.h:776
#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:269
static void table_endscan(TableScanDesc scan)
Definition tableam.h:1061
static TableScanDesc table_beginscan_tid(Relation rel, Snapshot snapshot)
Definition tableam.h:1035
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:446
static ItemPointer currtid_internal(Relation rel, const ItemPointerData *tid)
Definition tid.c:324
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 tid_offset(PG_FUNCTION_ARGS)
Definition tid.c:303
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:366
#define LDELIM
Definition tid.c:39
Datum tid_block(PG_FUNCTION_ARGS)
Definition tid.c:288
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178
List * textToQualifiedNameList(text *textval)
Definition varlena.c:2719