1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* tid.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* Functions for the built-in type tuple id
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2014-01-07 22:05:30 +01:00
|
|
|
* Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/utils/adt/tid.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* NOTES
|
1997-09-07 07:04:48 +02:00
|
|
|
* input routine largely stolen from boxin().
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1999-07-17 22:18:55 +02:00
|
|
|
#include "postgres.h"
|
2000-05-29 03:59:17 +02:00
|
|
|
|
2002-07-16 19:55:25 +02:00
|
|
|
#include <math.h>
|
|
|
|
#include <limits.h>
|
|
|
|
|
2000-05-29 03:59:17 +02:00
|
|
|
#include "access/heapam.h"
|
2008-05-12 02:00:54 +02:00
|
|
|
#include "access/sysattr.h"
|
2002-03-30 02:02:42 +01:00
|
|
|
#include "catalog/namespace.h"
|
2002-05-22 09:46:58 +02:00
|
|
|
#include "catalog/pg_type.h"
|
2003-05-13 01:08:52 +02:00
|
|
|
#include "libpq/pqformat.h"
|
2007-08-27 02:57:36 +02:00
|
|
|
#include "miscadmin.h"
|
2003-08-11 22:46:47 +02:00
|
|
|
#include "parser/parsetree.h"
|
2007-08-27 02:57:36 +02:00
|
|
|
#include "utils/acl.h"
|
2003-05-13 01:08:52 +02:00
|
|
|
#include "utils/builtins.h"
|
2008-06-19 02:46:06 +02:00
|
|
|
#include "utils/rel.h"
|
2013-07-25 22:32:02 +02:00
|
|
|
#include "utils/snapmgr.h"
|
2008-03-26 22:10:39 +01:00
|
|
|
#include "utils/tqual.h"
|
2003-05-13 01:08:52 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
#define DatumGetItemPointer(X) ((ItemPointer) DatumGetPointer(X))
|
|
|
|
#define ItemPointerGetDatum(X) PointerGetDatum(X)
|
2000-08-03 18:35:08 +02:00
|
|
|
#define PG_GETARG_ITEMPOINTER(n) DatumGetItemPointer(PG_GETARG_DATUM(n))
|
|
|
|
#define PG_RETURN_ITEMPOINTER(x) return ItemPointerGetDatum(x)
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
#define LDELIM '('
|
|
|
|
#define RDELIM ')'
|
|
|
|
#define DELIM ','
|
|
|
|
#define NTIDARGS 2
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* tidin
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
2000-08-03 18:35:08 +02:00
|
|
|
Datum
|
|
|
|
tidin(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-08-03 18:35:08 +02:00
|
|
|
char *str = PG_GETARG_CSTRING(0);
|
|
|
|
char *p,
|
1997-09-08 04:41:22 +02:00
|
|
|
*coord[NTIDARGS];
|
|
|
|
int i;
|
|
|
|
ItemPointer result;
|
|
|
|
BlockNumber blockNumber;
|
|
|
|
OffsetNumber offsetNumber;
|
2002-07-16 19:55:25 +02:00
|
|
|
char *badp;
|
|
|
|
int hold_offset;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
for (i = 0, p = str; *p && i < NTIDARGS && *p != RDELIM; p++)
|
|
|
|
if (*p == DELIM || (*p == LDELIM && !i))
|
|
|
|
coord[i++] = p + 1;
|
|
|
|
|
1999-10-11 08:28:29 +02:00
|
|
|
if (i < NTIDARGS)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("invalid input syntax for type tid: \"%s\"",
|
2003-07-27 06:53:12 +02:00
|
|
|
str)));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-07-16 19:55:25 +02:00
|
|
|
errno = 0;
|
|
|
|
blockNumber = strtoul(coord[0], &badp, 10);
|
|
|
|
if (errno || *badp != DELIM)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("invalid input syntax for type tid: \"%s\"",
|
2003-07-27 06:53:12 +02:00
|
|
|
str)));
|
2002-07-16 19:55:25 +02:00
|
|
|
|
|
|
|
hold_offset = strtol(coord[1], &badp, 10);
|
|
|
|
if (errno || *badp != RDELIM ||
|
|
|
|
hold_offset > USHRT_MAX || hold_offset < 0)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("invalid input syntax for type tid: \"%s\"",
|
2003-07-27 06:53:12 +02:00
|
|
|
str)));
|
|
|
|
|
2002-07-16 19:55:25 +02:00
|
|
|
offsetNumber = hold_offset;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
result = (ItemPointer) palloc(sizeof(ItemPointerData));
|
|
|
|
|
|
|
|
ItemPointerSet(result, blockNumber, offsetNumber);
|
|
|
|
|
2000-08-03 18:35:08 +02:00
|
|
|
PG_RETURN_ITEMPOINTER(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* tidout
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
2000-08-03 18:35:08 +02:00
|
|
|
Datum
|
|
|
|
tidout(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
ItemPointer itemPtr = PG_GETARG_ITEMPOINTER(0);
|
1997-09-08 04:41:22 +02:00
|
|
|
BlockNumber blockNumber;
|
|
|
|
OffsetNumber offsetNumber;
|
|
|
|
char buf[32];
|
1999-10-11 08:28:29 +02:00
|
|
|
|
2006-07-21 22:51:33 +02:00
|
|
|
blockNumber = BlockIdGetBlockNumber(&(itemPtr->ip_blkid));
|
1997-09-07 07:04:48 +02:00
|
|
|
offsetNumber = itemPtr->ip_posid;
|
|
|
|
|
2006-02-27 02:41:16 +01:00
|
|
|
/* Perhaps someday we should output this as a record. */
|
2002-08-28 22:46:24 +02:00
|
|
|
snprintf(buf, sizeof(buf), "(%u,%u)", blockNumber, offsetNumber);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-08-03 18:35:08 +02:00
|
|
|
PG_RETURN_CSTRING(pstrdup(buf));
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1999-10-11 08:28:29 +02:00
|
|
|
|
2003-05-13 01:08:52 +02:00
|
|
|
/*
|
|
|
|
* tidrecv - converts external binary format to tid
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
tidrecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
|
|
|
ItemPointer result;
|
|
|
|
BlockNumber blockNumber;
|
|
|
|
OffsetNumber offsetNumber;
|
|
|
|
|
|
|
|
blockNumber = pq_getmsgint(buf, sizeof(blockNumber));
|
|
|
|
offsetNumber = pq_getmsgint(buf, sizeof(offsetNumber));
|
|
|
|
|
|
|
|
result = (ItemPointer) palloc(sizeof(ItemPointerData));
|
|
|
|
|
|
|
|
ItemPointerSet(result, blockNumber, offsetNumber);
|
|
|
|
|
|
|
|
PG_RETURN_ITEMPOINTER(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* tidsend - converts tid to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
tidsend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ItemPointer itemPtr = PG_GETARG_ITEMPOINTER(0);
|
|
|
|
BlockId blockId;
|
|
|
|
BlockNumber blockNumber;
|
|
|
|
OffsetNumber offsetNumber;
|
|
|
|
StringInfoData buf;
|
|
|
|
|
|
|
|
blockId = &(itemPtr->ip_blkid);
|
|
|
|
blockNumber = BlockIdGetBlockNumber(blockId);
|
|
|
|
offsetNumber = itemPtr->ip_posid;
|
|
|
|
|
|
|
|
pq_begintypsend(&buf);
|
|
|
|
pq_sendint(&buf, blockNumber, sizeof(blockNumber));
|
|
|
|
pq_sendint(&buf, offsetNumber, sizeof(offsetNumber));
|
|
|
|
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
|
|
|
}
|
|
|
|
|
1999-10-11 08:28:29 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* PUBLIC ROUTINES *
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2000-08-03 18:35:08 +02:00
|
|
|
Datum
|
|
|
|
tideq(PG_FUNCTION_ARGS)
|
1999-10-11 08:28:29 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
|
|
|
|
ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2006-10-04 02:30:14 +02:00
|
|
|
PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) == 0);
|
1999-10-11 08:28:29 +02:00
|
|
|
}
|
|
|
|
|
2000-08-03 18:35:08 +02:00
|
|
|
Datum
|
|
|
|
tidne(PG_FUNCTION_ARGS)
|
1999-10-11 08:28:29 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
|
|
|
|
ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
|
2000-08-03 18:35:08 +02:00
|
|
|
|
2006-10-04 02:30:14 +02:00
|
|
|
PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) != 0);
|
1999-10-11 08:28:29 +02:00
|
|
|
}
|
|
|
|
|
2006-07-21 22:51:33 +02:00
|
|
|
Datum
|
|
|
|
tidlt(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
|
|
|
|
ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
|
|
|
|
|
2006-10-04 02:30:14 +02:00
|
|
|
PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) < 0);
|
2006-07-21 22:51:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
tidle(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
|
|
|
|
ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
|
|
|
|
|
2006-10-04 02:30:14 +02:00
|
|
|
PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) <= 0);
|
2006-07-21 22:51:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
tidgt(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
|
|
|
|
ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
|
|
|
|
|
2006-10-04 02:30:14 +02:00
|
|
|
PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) > 0);
|
2006-07-21 22:51:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
tidge(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
|
|
|
|
ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
|
|
|
|
|
2006-10-04 02:30:14 +02:00
|
|
|
PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) >= 0);
|
2006-07-21 22:51:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bttidcmp(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
|
|
|
|
ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
|
|
|
|
|
2006-08-25 06:06:58 +02:00
|
|
|
PG_RETURN_INT32(ItemPointerCompare(arg1, arg2));
|
2006-07-21 22:51:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
tidlarger(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
|
|
|
|
ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
|
|
|
|
|
2006-10-04 02:30:14 +02:00
|
|
|
PG_RETURN_ITEMPOINTER(ItemPointerCompare(arg1, arg2) >= 0 ? arg1 : arg2);
|
2006-07-21 22:51:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
tidsmaller(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
|
|
|
|
ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
|
|
|
|
|
2006-10-04 02:30:14 +02:00
|
|
|
PG_RETURN_ITEMPOINTER(ItemPointerCompare(arg1, arg2) <= 0 ? arg1 : arg2);
|
2006-07-21 22:51:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-10-11 08:28:29 +02:00
|
|
|
/*
|
|
|
|
* Functions to get latest tid of a specified tuple.
|
2000-06-09 03:11:16 +02:00
|
|
|
*
|
|
|
|
* Maybe these implementations should be moved to another place
|
|
|
|
*/
|
2001-09-17 02:29:10 +02:00
|
|
|
|
2001-10-25 07:50:21 +02:00
|
|
|
static ItemPointerData Current_last_tid = {{0, 0}, 0};
|
2001-09-17 02:29:10 +02:00
|
|
|
|
|
|
|
void
|
|
|
|
setLastTid(const ItemPointer tid)
|
|
|
|
{
|
|
|
|
Current_last_tid = *tid;
|
|
|
|
}
|
|
|
|
|
2002-05-22 09:46:58 +02:00
|
|
|
/*
|
|
|
|
* Handle CTIDs of views.
|
|
|
|
* CTID should be defined in the view and it must
|
|
|
|
* correspond to the CTID of a base relation.
|
|
|
|
*/
|
|
|
|
static Datum
|
2002-09-04 22:31:48 +02:00
|
|
|
currtid_for_view(Relation viewrel, ItemPointer tid)
|
2002-05-22 09:46:58 +02:00
|
|
|
{
|
|
|
|
TupleDesc att = RelationGetDescr(viewrel);
|
2002-09-04 22:31:48 +02:00
|
|
|
RuleLock *rulelock;
|
|
|
|
RewriteRule *rewrite;
|
|
|
|
int i,
|
|
|
|
natts = att->natts,
|
|
|
|
tididx = -1;
|
2002-05-22 09:46:58 +02:00
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
for (i = 0; i < natts; i++)
|
2002-05-22 09:46:58 +02:00
|
|
|
{
|
2004-05-07 02:24:59 +02:00
|
|
|
if (strcmp(NameStr(att->attrs[i]->attname), "ctid") == 0)
|
2002-05-22 09:46:58 +02:00
|
|
|
{
|
|
|
|
if (att->attrs[i]->atttypid != TIDOID)
|
|
|
|
elog(ERROR, "ctid isn't of type TID");
|
|
|
|
tididx = i;
|
2003-08-11 22:46:47 +02:00
|
|
|
break;
|
2002-05-22 09:46:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tididx < 0)
|
2003-07-27 06:53:12 +02:00
|
|
|
elog(ERROR, "currtid cannot handle views with no CTID");
|
|
|
|
rulelock = viewrel->rd_rules;
|
|
|
|
if (!rulelock)
|
2002-05-22 09:46:58 +02:00
|
|
|
elog(ERROR, "the view has no rules");
|
|
|
|
for (i = 0; i < rulelock->numLocks; i++)
|
|
|
|
{
|
|
|
|
rewrite = rulelock->rules[i];
|
|
|
|
if (rewrite->event == CMD_SELECT)
|
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
Query *query;
|
2002-05-22 09:46:58 +02:00
|
|
|
TargetEntry *tle;
|
|
|
|
|
2004-05-31 01:40:41 +02:00
|
|
|
if (list_length(rewrite->actions) != 1)
|
2002-05-22 09:46:58 +02:00
|
|
|
elog(ERROR, "only one select rule is allowed in views");
|
2004-05-26 06:41:50 +02:00
|
|
|
query = (Query *) linitial(rewrite->actions);
|
2004-08-29 07:07:03 +02:00
|
|
|
tle = get_tle_by_resno(query->targetList, tididx + 1);
|
2003-07-27 06:53:12 +02:00
|
|
|
if (tle && tle->expr && IsA(tle->expr, Var))
|
2002-05-22 09:46:58 +02:00
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
Var *var = (Var *) tle->expr;
|
2002-05-22 09:46:58 +02:00
|
|
|
RangeTblEntry *rte;
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2011-10-11 20:20:06 +02:00
|
|
|
if (!IS_SPECIAL_VARNO(var->varno) &&
|
2003-07-27 06:53:12 +02:00
|
|
|
var->varattno == SelfItemPointerAttributeNumber)
|
2002-05-22 09:46:58 +02:00
|
|
|
{
|
2003-08-11 22:46:47 +02:00
|
|
|
rte = rt_fetch(var->varno, query->rtable);
|
2002-05-22 09:46:58 +02:00
|
|
|
if (rte)
|
|
|
|
{
|
|
|
|
heap_close(viewrel, AccessShareLock);
|
|
|
|
return DirectFunctionCall2(currtid_byreloid, ObjectIdGetDatum(rte->relid), PointerGetDatum(tid));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-07-27 06:53:12 +02:00
|
|
|
elog(ERROR, "currtid cannot handle this view");
|
2002-05-22 09:46:58 +02:00
|
|
|
return (Datum) 0;
|
|
|
|
}
|
|
|
|
|
2000-06-09 03:11:16 +02:00
|
|
|
Datum
|
|
|
|
currtid_byreloid(PG_FUNCTION_ARGS)
|
1999-10-11 08:28:29 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
Oid reloid = PG_GETARG_OID(0);
|
|
|
|
ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
|
2001-07-06 11:41:36 +02:00
|
|
|
ItemPointer result;
|
2001-03-22 05:01:46 +01:00
|
|
|
Relation rel;
|
2007-08-27 02:57:36 +02:00
|
|
|
AclResult aclresult;
|
2013-07-25 22:32:02 +02:00
|
|
|
Snapshot snapshot;
|
1999-10-11 08:28:29 +02:00
|
|
|
|
|
|
|
result = (ItemPointer) palloc(sizeof(ItemPointerData));
|
2001-10-25 07:50:21 +02:00
|
|
|
if (!reloid)
|
|
|
|
{
|
|
|
|
*result = Current_last_tid;
|
|
|
|
PG_RETURN_ITEMPOINTER(result);
|
|
|
|
}
|
2002-03-30 02:02:42 +01:00
|
|
|
|
|
|
|
rel = heap_open(reloid, AccessShareLock);
|
2007-08-27 02:57:36 +02:00
|
|
|
|
|
|
|
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
|
|
|
|
ACL_SELECT);
|
|
|
|
if (aclresult != ACLCHECK_OK)
|
|
|
|
aclcheck_error(aclresult, ACL_KIND_CLASS,
|
|
|
|
RelationGetRelationName(rel));
|
|
|
|
|
2002-05-22 09:46:58 +02:00
|
|
|
if (rel->rd_rel->relkind == RELKIND_VIEW)
|
|
|
|
return currtid_for_view(rel, tid);
|
2002-03-30 02:02:42 +01:00
|
|
|
|
2001-07-06 11:41:36 +02:00
|
|
|
ItemPointerCopy(tid, result);
|
2013-07-25 22:32:02 +02:00
|
|
|
|
|
|
|
snapshot = RegisterSnapshot(GetLatestSnapshot());
|
|
|
|
heap_get_latest_tid(rel, snapshot, result);
|
|
|
|
UnregisterSnapshot(snapshot);
|
2002-03-30 02:02:42 +01:00
|
|
|
|
|
|
|
heap_close(rel, AccessShareLock);
|
1999-10-11 08:28:29 +02:00
|
|
|
|
2000-08-03 18:35:08 +02:00
|
|
|
PG_RETURN_ITEMPOINTER(result);
|
2000-06-09 03:11:16 +02:00
|
|
|
}
|
1999-10-11 08:28:29 +02:00
|
|
|
|
2000-06-09 03:11:16 +02:00
|
|
|
Datum
|
|
|
|
currtid_byrelname(PG_FUNCTION_ARGS)
|
1999-10-11 08:28:29 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
text *relname = PG_GETARG_TEXT_P(0);
|
|
|
|
ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
|
2001-07-06 11:41:36 +02:00
|
|
|
ItemPointer result;
|
2002-03-30 02:02:42 +01:00
|
|
|
RangeVar *relrv;
|
2001-03-22 05:01:46 +01:00
|
|
|
Relation rel;
|
2007-08-27 02:57:36 +02:00
|
|
|
AclResult aclresult;
|
2013-07-25 22:32:02 +02:00
|
|
|
Snapshot snapshot;
|
1999-10-11 08:28:29 +02:00
|
|
|
|
2005-05-27 02:57:49 +02:00
|
|
|
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
|
2002-03-30 02:02:42 +01:00
|
|
|
rel = heap_openrv(relrv, AccessShareLock);
|
2007-08-27 02:57:36 +02:00
|
|
|
|
|
|
|
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
|
|
|
|
ACL_SELECT);
|
|
|
|
if (aclresult != ACLCHECK_OK)
|
|
|
|
aclcheck_error(aclresult, ACL_KIND_CLASS,
|
|
|
|
RelationGetRelationName(rel));
|
|
|
|
|
2002-05-22 09:46:58 +02:00
|
|
|
if (rel->rd_rel->relkind == RELKIND_VIEW)
|
|
|
|
return currtid_for_view(rel, tid);
|
1999-10-11 08:28:29 +02:00
|
|
|
|
|
|
|
result = (ItemPointer) palloc(sizeof(ItemPointerData));
|
2001-07-06 11:41:36 +02:00
|
|
|
ItemPointerCopy(tid, result);
|
2000-06-09 03:11:16 +02:00
|
|
|
|
2013-07-25 22:32:02 +02:00
|
|
|
snapshot = RegisterSnapshot(GetLatestSnapshot());
|
|
|
|
heap_get_latest_tid(rel, snapshot, result);
|
|
|
|
UnregisterSnapshot(snapshot);
|
2002-03-30 02:02:42 +01:00
|
|
|
|
|
|
|
heap_close(rel, AccessShareLock);
|
1999-10-11 08:28:29 +02:00
|
|
|
|
2000-08-03 18:35:08 +02:00
|
|
|
PG_RETURN_ITEMPOINTER(result);
|
2000-06-09 03:11:16 +02:00
|
|
|
}
|