]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/adt/tid.c
Add support for EUI-64 MAC addresses as macaddr8
[postgresql] / src / backend / utils / adt / tid.c
index d90c20adf981bce9e8bbd0f72c450ce7b6c12ffd..49a5a157b94e24b5781c0f9bb6cb09c56c03891a 100644 (file)
@@ -3,29 +3,37 @@
  * tid.c
  *       Functions for the built-in type tuple id
  *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.35 2002/08/29 00:17:05 tgl Exp $
+ *       src/backend/utils/adt/tid.c
  *
  * NOTES
  *       input routine largely stolen from boxin().
  *
  *-------------------------------------------------------------------------
  */
-
 #include "postgres.h"
 
-#include <errno.h>
 #include <math.h>
 #include <limits.h>
 
 #include "access/heapam.h"
+#include "access/sysattr.h"
 #include "catalog/namespace.h"
-#include "utils/builtins.h"
 #include "catalog/pg_type.h"
+#include "libpq/pqformat.h"
+#include "miscadmin.h"
+#include "parser/parsetree.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/rel.h"
+#include "utils/snapmgr.h"
+#include "utils/tqual.h"
+#include "utils/varlena.h"
+
 
 #define DatumGetItemPointer(X)  ((ItemPointer) DatumGetPointer(X))
 #define ItemPointerGetDatum(X)  PointerGetDatum(X)
@@ -59,17 +67,27 @@ tidin(PG_FUNCTION_ARGS)
                        coord[i++] = p + 1;
 
        if (i < NTIDARGS)
-               elog(ERROR, "invalid tid format: '%s'", str);
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                                errmsg("invalid input syntax for type %s: \"%s\"",
+                                               "tid", str)));
 
        errno = 0;
        blockNumber = strtoul(coord[0], &badp, 10);
        if (errno || *badp != DELIM)
-               elog(ERROR, "tidin: invalid value.");
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                                errmsg("invalid input syntax for type %s: \"%s\"",
+                                               "tid", str)));
 
        hold_offset = strtol(coord[1], &badp, 10);
        if (errno || *badp != RDELIM ||
                hold_offset > USHRT_MAX || hold_offset < 0)
-               elog(ERROR, "tidin: invalid value.");
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                                errmsg("invalid input syntax for type %s: \"%s\"",
+                                               "tid", str)));
+
        offsetNumber = hold_offset;
 
        result = (ItemPointer) palloc(sizeof(ItemPointerData));
@@ -87,25 +105,62 @@ Datum
 tidout(PG_FUNCTION_ARGS)
 {
        ItemPointer itemPtr = PG_GETARG_ITEMPOINTER(0);
-       BlockId         blockId;
        BlockNumber blockNumber;
        OffsetNumber offsetNumber;
        char            buf[32];
-       static char *invalidTid = "()";
-
-       if (!ItemPointerIsValid(itemPtr))
-               PG_RETURN_CSTRING(pstrdup(invalidTid));
 
-       blockId = &(itemPtr->ip_blkid);
-
-       blockNumber = BlockIdGetBlockNumber(blockId);
+       blockNumber = BlockIdGetBlockNumber(&(itemPtr->ip_blkid));
        offsetNumber = itemPtr->ip_posid;
 
+       /* Perhaps someday we should output this as a record. */
        snprintf(buf, sizeof(buf), "(%u,%u)", blockNumber, offsetNumber);
 
        PG_RETURN_CSTRING(pstrdup(buf));
 }
 
+/*
+ *             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));
+}
+
 /*****************************************************************************
  *      PUBLIC ROUTINES                                                                                                                 *
  *****************************************************************************/
@@ -116,23 +171,81 @@ tideq(PG_FUNCTION_ARGS)
        ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
        ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
 
-       PG_RETURN_BOOL(BlockIdGetBlockNumber(&(arg1->ip_blkid)) ==
-                                  BlockIdGetBlockNumber(&(arg2->ip_blkid)) &&
-                                  arg1->ip_posid == arg2->ip_posid);
+       PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) == 0);
 }
 
-#ifdef NOT_USED
 Datum
 tidne(PG_FUNCTION_ARGS)
 {
        ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
        ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
 
-       PG_RETURN_BOOL(BlockIdGetBlockNumber(&(arg1->ip_blkid)) !=
-                                  BlockIdGetBlockNumber(&(arg2->ip_blkid)) ||
-                                  arg1->ip_posid != arg2->ip_posid);
+       PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) != 0);
+}
+
+Datum
+tidlt(PG_FUNCTION_ARGS)
+{
+       ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
+       ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
+
+       PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) < 0);
+}
+
+Datum
+tidle(PG_FUNCTION_ARGS)
+{
+       ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
+       ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
+
+       PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) <= 0);
+}
+
+Datum
+tidgt(PG_FUNCTION_ARGS)
+{
+       ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
+       ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
+
+       PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) > 0);
 }
-#endif
+
+Datum
+tidge(PG_FUNCTION_ARGS)
+{
+       ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
+       ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
+
+       PG_RETURN_BOOL(ItemPointerCompare(arg1, arg2) >= 0);
+}
+
+Datum
+bttidcmp(PG_FUNCTION_ARGS)
+{
+       ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
+       ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
+
+       PG_RETURN_INT32(ItemPointerCompare(arg1, arg2));
+}
+
+Datum
+tidlarger(PG_FUNCTION_ARGS)
+{
+       ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
+       ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
+
+       PG_RETURN_ITEMPOINTER(ItemPointerCompare(arg1, arg2) >= 0 ? arg1 : arg2);
+}
+
+Datum
+tidsmaller(PG_FUNCTION_ARGS)
+{
+       ItemPointer arg1 = PG_GETARG_ITEMPOINTER(0);
+       ItemPointer arg2 = PG_GETARG_ITEMPOINTER(1);
+
+       PG_RETURN_ITEMPOINTER(ItemPointerCompare(arg1, arg2) <= 0 ? arg1 : arg2);
+}
+
 
 /*
  *     Functions to get latest tid of a specified tuple.
@@ -154,45 +267,51 @@ setLastTid(const ItemPointer tid)
  *             correspond to the CTID of a base relation.
  */
 static Datum
-currtid_for_view(Relation viewrel, ItemPointer tid) 
+currtid_for_view(Relation viewrel, ItemPointer tid)
 {
        TupleDesc       att = RelationGetDescr(viewrel);
-       RuleLock        *rulelock;
-       RewriteRule     *rewrite;
-       int     i, natts = att->natts, tididx = -1;
+       RuleLock   *rulelock;
+       RewriteRule *rewrite;
+       int                     i,
+                               natts = att->natts,
+                               tididx = -1;
 
-       for (i = 0; i < natts ; i++)
+       for (i = 0; i < natts; i++)
        {
-               if (strcasecmp(NameStr(att->attrs[i]->attname), "ctid") == 0)
+               if (strcmp(NameStr(att->attrs[i]->attname), "ctid") == 0)
                {
                        if (att->attrs[i]->atttypid != TIDOID)
                                elog(ERROR, "ctid isn't of type TID");
                        tididx = i;
+                       break;
                }
        }
        if (tididx < 0)
-               elog(ERROR, "currtid can't handle views with no CTID");
-       if (rulelock = viewrel->rd_rules, !rulelock)
+               elog(ERROR, "currtid cannot handle views with no CTID");
+       rulelock = viewrel->rd_rules;
+       if (!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;
+                       Query      *query;
                        TargetEntry *tle;
 
-                       if (length(rewrite->actions) != 1)
+                       if (list_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)
+                       query = (Query *) linitial(rewrite->actions);
+                       tle = get_tle_by_resno(query->targetList, tididx + 1);
+                       if (tle && tle->expr && IsA(tle->expr, Var))
                        {
-                               Var *var = (Var *) tle->expr;
+                               Var                *var = (Var *) tle->expr;
                                RangeTblEntry *rte;
-                               if (var->varno > 0 && var->varno < INNER && var->varattno == SelfItemPointerAttributeNumber)
+
+                               if (!IS_SPECIAL_VARNO(var->varno) &&
+                                       var->varattno == SelfItemPointerAttributeNumber)
                                {
-                                       rte = (RangeTblEntry *) nth(var->varno - 1, query->rtable);
+                                       rte = rt_fetch(var->varno, query->rtable);
                                        if (rte)
                                        {
                                                heap_close(viewrel, AccessShareLock);
@@ -203,7 +322,7 @@ currtid_for_view(Relation viewrel, ItemPointer tid)
                        break;
                }
        }
-       elog(ERROR, "currtid can't handle this view");
+       elog(ERROR, "currtid cannot handle this view");
        return (Datum) 0;
 }
 
@@ -214,6 +333,8 @@ currtid_byreloid(PG_FUNCTION_ARGS)
        ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
        ItemPointer result;
        Relation        rel;
+       AclResult       aclresult;
+       Snapshot        snapshot;
 
        result = (ItemPointer) palloc(sizeof(ItemPointerData));
        if (!reloid)
@@ -223,11 +344,21 @@ currtid_byreloid(PG_FUNCTION_ARGS)
        }
 
        rel = heap_open(reloid, AccessShareLock);
+
+       aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
+                                                                 ACL_SELECT);
+       if (aclresult != ACLCHECK_OK)
+               aclcheck_error(aclresult, ACL_KIND_CLASS,
+                                          RelationGetRelationName(rel));
+
        if (rel->rd_rel->relkind == RELKIND_VIEW)
                return currtid_for_view(rel, tid);
 
        ItemPointerCopy(tid, result);
-       heap_get_latest_tid(rel, SnapshotNow, result);
+
+       snapshot = RegisterSnapshot(GetLatestSnapshot());
+       heap_get_latest_tid(rel, snapshot, result);
+       UnregisterSnapshot(snapshot);
 
        heap_close(rel, AccessShareLock);
 
@@ -237,22 +368,32 @@ currtid_byreloid(PG_FUNCTION_ARGS)
 Datum
 currtid_byrelname(PG_FUNCTION_ARGS)
 {
-       text       *relname = PG_GETARG_TEXT_P(0);
+       text       *relname = PG_GETARG_TEXT_PP(0);
        ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
        ItemPointer result;
        RangeVar   *relrv;
        Relation        rel;
+       AclResult       aclresult;
+       Snapshot        snapshot;
 
-       relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
-                                                                                                               "currtid_byrelname"));
+       relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
        rel = heap_openrv(relrv, AccessShareLock);
+
+       aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
+                                                                 ACL_SELECT);
+       if (aclresult != ACLCHECK_OK)
+               aclcheck_error(aclresult, ACL_KIND_CLASS,
+                                          RelationGetRelationName(rel));
+
        if (rel->rd_rel->relkind == RELKIND_VIEW)
                return currtid_for_view(rel, tid);
 
        result = (ItemPointer) palloc(sizeof(ItemPointerData));
        ItemPointerCopy(tid, result);
 
-       heap_get_latest_tid(rel, SnapshotNow, result);
+       snapshot = RegisterSnapshot(GetLatestSnapshot());
+       heap_get_latest_tid(rel, snapshot, result);
+       UnregisterSnapshot(snapshot);
 
        heap_close(rel, AccessShareLock);