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
|
|
|
*
|
2002-06-20 22:29:54 +02:00
|
|
|
* Portions Copyright (c) 1996-2002, 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
|
2002-06-20 22:29:54 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.31 2002/06/20 20:29:38 momjian Exp $
|
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
|
|
|
|
|
|
|
#include "access/heapam.h"
|
2002-03-30 02:02:42 +01:00
|
|
|
#include "catalog/namespace.h"
|
1999-07-16 05:14:30 +02:00
|
|
|
#include "utils/builtins.h"
|
2002-05-22 09:46:58 +02:00
|
|
|
#include "catalog/pg_type.h"
|
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;
|
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)
|
2000-08-03 18:35:08 +02:00
|
|
|
elog(ERROR, "invalid tid format: '%s'", str);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
blockNumber = (BlockNumber) atoi(coord[0]);
|
|
|
|
offsetNumber = (OffsetNumber) atoi(coord[1]);
|
|
|
|
|
|
|
|
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);
|
2000-08-03 18:35:08 +02:00
|
|
|
BlockId blockId;
|
1997-09-08 04:41:22 +02:00
|
|
|
BlockNumber blockNumber;
|
|
|
|
OffsetNumber offsetNumber;
|
|
|
|
char buf[32];
|
1999-10-11 08:28:29 +02:00
|
|
|
static char *invalidTid = "()";
|
|
|
|
|
2000-08-03 18:35:08 +02:00
|
|
|
if (!ItemPointerIsValid(itemPtr))
|
|
|
|
PG_RETURN_CSTRING(pstrdup(invalidTid));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
blockId = &(itemPtr->ip_blkid);
|
|
|
|
|
|
|
|
blockNumber = BlockIdGetBlockNumber(blockId);
|
|
|
|
offsetNumber = itemPtr->ip_posid;
|
|
|
|
|
2000-08-03 18:35:08 +02:00
|
|
|
sprintf(buf, "(%d,%d)", (int) blockNumber, (int) 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
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* 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
|
|
|
|
2000-08-03 18:35:08 +02:00
|
|
|
PG_RETURN_BOOL(BlockIdGetBlockNumber(&(arg1->ip_blkid)) ==
|
|
|
|
BlockIdGetBlockNumber(&(arg2->ip_blkid)) &&
|
|
|
|
arg1->ip_posid == arg2->ip_posid);
|
1999-10-11 08:28:29 +02:00
|
|
|
}
|
|
|
|
|
2000-06-09 00:38:00 +02:00
|
|
|
#ifdef NOT_USED
|
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
|
|
|
|
|
|
|
PG_RETURN_BOOL(BlockIdGetBlockNumber(&(arg1->ip_blkid)) !=
|
|
|
|
BlockIdGetBlockNumber(&(arg2->ip_blkid)) ||
|
|
|
|
arg1->ip_posid != arg2->ip_posid);
|
1999-10-11 08:28:29 +02:00
|
|
|
}
|
2000-06-09 00:38:00 +02:00
|
|
|
#endif
|
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
|
|
|
|
currtid_for_view(Relation viewrel, ItemPointer tid)
|
|
|
|
{
|
|
|
|
TupleDesc att = RelationGetDescr(viewrel);
|
|
|
|
RuleLock *rulelock;
|
|
|
|
RewriteRule *rewrite;
|
|
|
|
int i, natts = att->natts, tididx = -1;
|
|
|
|
|
|
|
|
for (i = 0; i < natts ; i++)
|
|
|
|
{
|
|
|
|
if (strcasecmp(NameStr(att->attrs[i]->attname), "ctid") == 0)
|
|
|
|
{
|
|
|
|
if (att->attrs[i]->atttypid != TIDOID)
|
|
|
|
elog(ERROR, "ctid isn't of type TID");
|
|
|
|
tididx = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tididx < 0)
|
|
|
|
elog(ERROR, "currtid can't handle views with no CTID");
|
|
|
|
if (rulelock = viewrel->rd_rules, !rulelock)
|
|
|
|
elog(ERROR, "the view has no rules");
|
|
|
|
for (i = 0; i < rulelock->numLocks; i++)
|
|
|
|
{
|
|
|
|
rewrite = rulelock->rules[i];
|
|
|
|
if (rewrite->event == CMD_SELECT)
|
|
|
|
{
|
|
|
|
Query *query;
|
|
|
|
TargetEntry *tle;
|
|
|
|
|
|
|
|
if (length(rewrite->actions) != 1)
|
|
|
|
elog(ERROR, "only one select rule is allowed in views");
|
|
|
|
query = (Query *) lfirst(rewrite->actions);
|
|
|
|
tle = (TargetEntry *) nth(tididx, query->targetList);
|
|
|
|
if (tle && tle->expr && nodeTag(tle->expr) == T_Var)
|
|
|
|
{
|
|
|
|
Var *var = (Var *) tle->expr;
|
|
|
|
RangeTblEntry *rte;
|
|
|
|
if (var->varno > 0 && var->varno < INNER && var->varattno == SelfItemPointerAttributeNumber)
|
|
|
|
{
|
|
|
|
rte = (RangeTblEntry *) nth(var->varno - 1, query->rtable);
|
|
|
|
if (rte)
|
|
|
|
{
|
|
|
|
heap_close(viewrel, AccessShareLock);
|
|
|
|
return DirectFunctionCall2(currtid_byreloid, ObjectIdGetDatum(rte->relid), PointerGetDatum(tid));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elog(ERROR, "currtid can't handle this view");
|
|
|
|
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;
|
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);
|
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);
|
2002-03-30 02:02:42 +01:00
|
|
|
heap_get_latest_tid(rel, SnapshotNow, result);
|
|
|
|
|
|
|
|
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;
|
1999-10-11 08:28:29 +02:00
|
|
|
|
2002-03-30 02:02:42 +01:00
|
|
|
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
|
|
|
|
"currtid_byrelname"));
|
|
|
|
rel = heap_openrv(relrv, AccessShareLock);
|
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
|
|
|
|
2002-03-30 02:02:42 +01:00
|
|
|
heap_get_latest_tid(rel, SnapshotNow, result);
|
|
|
|
|
|
|
|
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
|
|
|
}
|