On Fri, Jun 26, 2020 at 01:11:55PM +0900, Michael Paquier wrote:
> From what I can see on this thread, we could just remove currtid() per
> the arguments of the RETURNING ctid clause supported since PG 8.2, but
> it would make more sense to me to just remove both currtid/currtid2()
> at once.

The CF bot is complaining, so here is a rebase for the main patch.
Opinions are welcome about the arguments of upthread.
--
Michael
From 9da62abad29e5b2b8a8b24498eba7a2c3f718f9b Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@paquier.xyz>
Date: Wed, 3 Jun 2020 10:49:41 +0900
Subject: [PATCH v2] Remove currtid() and currtid2()

Those two functions have been used within the Postgres ODBC driver in
the old days, requiring them when connecting to Postgres 8.1 or older.
In 8.2, support for RETURNING has allowed the driver to fetch ctids
by directly using this clause.
---
 src/include/access/heapam.h            |   1 -
 src/include/catalog/pg_proc.dat        |   7 -
 src/backend/executor/nodeModifyTable.c |   1 -
 src/backend/utils/adt/tid.c            | 177 -------------------------
 src/test/regress/expected/tid.out      |  88 ------------
 src/test/regress/sql/tid.sql           |  52 --------
 6 files changed, 326 deletions(-)

diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 92b19dba32..54b2eb7378 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -129,7 +129,6 @@ extern bool heap_hot_search_buffer(ItemPointer tid, Relation relation,
 								   bool *all_dead, bool first_call);
 
 extern void heap_get_latest_tid(TableScanDesc scan, ItemPointer tid);
-extern void setLastTid(const ItemPointer tid);
 
 extern BulkInsertState GetBulkInsertState(void);
 extern void FreeBulkInsertState(BulkInsertState);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 687509ba92..d9ea8c8244 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -2542,13 +2542,6 @@
 { oid => '1292',
   proname => 'tideq', proleakproof => 't', prorettype => 'bool',
   proargtypes => 'tid tid', prosrc => 'tideq' },
-{ oid => '1293', descr => 'latest tid of a tuple',
-  proname => 'currtid', provolatile => 'v', proparallel => 'u',
-  prorettype => 'tid', proargtypes => 'oid tid', prosrc => 'currtid_byreloid' },
-{ oid => '1294', descr => 'latest tid of a tuple',
-  proname => 'currtid2', provolatile => 'v', proparallel => 'u',
-  prorettype => 'tid', proargtypes => 'text tid',
-  prosrc => 'currtid_byrelname' },
 { oid => '1265',
   proname => 'tidne', proleakproof => 't', prorettype => 'bool',
   proargtypes => 'tid tid', prosrc => 'tidne' },
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 20a4c474cc..fc53a12d56 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -629,7 +629,6 @@ ExecInsert(ModifyTableState *mtstate,
 	if (canSetTag)
 	{
 		(estate->es_processed)++;
-		setLastTid(&slot->tts_tid);
 	}
 
 	/*
diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c
index 509a0fdffc..29dddb20e6 100644
--- a/src/backend/utils/adt/tid.c
+++ b/src/backend/utils/adt/tid.c
@@ -267,180 +267,3 @@ hashtidextended(PG_FUNCTION_ARGS)
 							 sizeof(BlockIdData) + sizeof(OffsetNumber),
 							 seed);
 }
-
-
-/*
- *	Functions to get latest tid of a specified tuple.
- *
- *	Maybe these implementations should be moved to another place
- */
-
-static ItemPointerData Current_last_tid = {{0, 0}, 0};
-
-void
-setLastTid(const ItemPointer tid)
-{
-	Current_last_tid = *tid;
-}
-
-/*
- *	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++)
-	{
-		Form_pg_attribute attr = TupleDescAttr(att, i);
-
-		if (strcmp(NameStr(attr->attname), "ctid") == 0)
-		{
-			if (attr->atttypid != TIDOID)
-				elog(ERROR, "ctid isn't of type TID");
-			tididx = i;
-			break;
-		}
-	}
-	if (tididx < 0)
-		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;
-			TargetEntry *tle;
-
-			if (list_length(rewrite->actions) != 1)
-				elog(ERROR, "only one select rule is allowed in views");
-			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;
-				RangeTblEntry *rte;
-
-				if (!IS_SPECIAL_VARNO(var->varno) &&
-					var->varattno == SelfItemPointerAttributeNumber)
-				{
-					rte = rt_fetch(var->varno, query->rtable);
-					if (rte)
-					{
-						Datum		result;
-
-						result = DirectFunctionCall2(currtid_byreloid,
-													 ObjectIdGetDatum(rte->relid),
-													 PointerGetDatum(tid));
-						table_close(viewrel, AccessShareLock);
-						return result;
-					}
-				}
-			}
-			break;
-		}
-	}
-	elog(ERROR, "currtid cannot handle this view");
-	return (Datum) 0;
-}
-
-Datum
-currtid_byreloid(PG_FUNCTION_ARGS)
-{
-	Oid			reloid = PG_GETARG_OID(0);
-	ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
-	ItemPointer result;
-	Relation	rel;
-	AclResult	aclresult;
-	Snapshot	snapshot;
-	TableScanDesc scan;
-
-	result = (ItemPointer) palloc(sizeof(ItemPointerData));
-	if (!reloid)
-	{
-		*result = Current_last_tid;
-		PG_RETURN_ITEMPOINTER(result);
-	}
-
-	rel = table_open(reloid, AccessShareLock);
-
-	aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
-								  ACL_SELECT);
-	if (aclresult != ACLCHECK_OK)
-		aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind),
-					   RelationGetRelationName(rel));
-
-	if (rel->rd_rel->relkind == RELKIND_VIEW)
-		return currtid_for_view(rel, tid);
-
-	if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
-		elog(ERROR, "cannot look at latest visible tid for relation \"%s.%s\"",
-			 get_namespace_name(RelationGetNamespace(rel)),
-			 RelationGetRelationName(rel));
-
-	ItemPointerCopy(tid, result);
-
-	snapshot = RegisterSnapshot(GetLatestSnapshot());
-	scan = table_beginscan_tid(rel, snapshot);
-	table_tuple_get_latest_tid(scan, result);
-	table_endscan(scan);
-	UnregisterSnapshot(snapshot);
-
-	table_close(rel, AccessShareLock);
-
-	PG_RETURN_ITEMPOINTER(result);
-}
-
-Datum
-currtid_byrelname(PG_FUNCTION_ARGS)
-{
-	text	   *relname = PG_GETARG_TEXT_PP(0);
-	ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
-	ItemPointer result;
-	RangeVar   *relrv;
-	Relation	rel;
-	AclResult	aclresult;
-	Snapshot	snapshot;
-	TableScanDesc scan;
-
-	relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
-	rel = table_openrv(relrv, AccessShareLock);
-
-	aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
-								  ACL_SELECT);
-	if (aclresult != ACLCHECK_OK)
-		aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind),
-					   RelationGetRelationName(rel));
-
-	if (rel->rd_rel->relkind == RELKIND_VIEW)
-		return currtid_for_view(rel, tid);
-
-	if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
-		elog(ERROR, "cannot look at latest visible tid for relation \"%s.%s\"",
-			 get_namespace_name(RelationGetNamespace(rel)),
-			 RelationGetRelationName(rel));
-
-	result = (ItemPointer) palloc(sizeof(ItemPointerData));
-	ItemPointerCopy(tid, result);
-
-	snapshot = RegisterSnapshot(GetLatestSnapshot());
-	scan = table_beginscan_tid(rel, snapshot);
-	table_tuple_get_latest_tid(scan, result);
-	table_endscan(scan);
-	UnregisterSnapshot(snapshot);
-
-	table_close(rel, AccessShareLock);
-
-	PG_RETURN_ITEMPOINTER(result);
-}
diff --git a/src/test/regress/expected/tid.out b/src/test/regress/expected/tid.out
index e7e0d74780..f6971796f3 100644
--- a/src/test/regress/expected/tid.out
+++ b/src/test/regress/expected/tid.out
@@ -15,92 +15,4 @@ SELECT max(ctid) FROM tid_tab;
 (1 row)
 
 TRUNCATE tid_tab;
--- Tests for currtid() and currtid2() with various relation kinds
--- Materialized view
-CREATE MATERIALIZED VIEW tid_matview AS SELECT a FROM tid_tab;
-SELECT currtid('tid_matview'::regclass::oid, '(0,1)'::tid); -- fails
-ERROR:  tid (0, 1) is not valid for relation "tid_matview"
-SELECT currtid2('tid_matview'::text, '(0,1)'::tid); -- fails
-ERROR:  tid (0, 1) is not valid for relation "tid_matview"
-INSERT INTO tid_tab VALUES (1);
-REFRESH MATERIALIZED VIEW tid_matview;
-SELECT currtid('tid_matview'::regclass::oid, '(0,1)'::tid); -- ok
- currtid 
----------
- (0,1)
-(1 row)
-
-SELECT currtid2('tid_matview'::text, '(0,1)'::tid); -- ok
- currtid2 
-----------
- (0,1)
-(1 row)
-
-DROP MATERIALIZED VIEW tid_matview;
-TRUNCATE tid_tab;
--- Sequence
-CREATE SEQUENCE tid_seq;
-SELECT currtid('tid_seq'::regclass::oid, '(0,1)'::tid); -- ok
- currtid 
----------
- (0,1)
-(1 row)
-
-SELECT currtid2('tid_seq'::text, '(0,1)'::tid); -- ok
- currtid2 
-----------
- (0,1)
-(1 row)
-
-DROP SEQUENCE tid_seq;
--- Index, fails with incorrect relation type
-CREATE INDEX tid_ind ON tid_tab(a);
-SELECT currtid('tid_ind'::regclass::oid, '(0,1)'::tid); -- fails
-ERROR:  "tid_ind" is an index
-SELECT currtid2('tid_ind'::text, '(0,1)'::tid); -- fails
-ERROR:  "tid_ind" is an index
-DROP INDEX tid_ind;
--- Partitioned table, no storage
-CREATE TABLE tid_part (a int) PARTITION BY RANGE (a);
-SELECT currtid('tid_part'::regclass::oid, '(0,1)'::tid); -- fails
-ERROR:  cannot look at latest visible tid for relation "public.tid_part"
-SELECT currtid2('tid_part'::text, '(0,1)'::tid); -- fails
-ERROR:  cannot look at latest visible tid for relation "public.tid_part"
-DROP TABLE tid_part;
--- Views
--- ctid not defined in the view
-CREATE VIEW tid_view_no_ctid AS SELECT a FROM tid_tab;
-SELECT currtid('tid_view_no_ctid'::regclass::oid, '(0,1)'::tid); -- fails
-ERROR:  currtid cannot handle views with no CTID
-SELECT currtid2('tid_view_no_ctid'::text, '(0,1)'::tid); -- fails
-ERROR:  currtid cannot handle views with no CTID
-DROP VIEW tid_view_no_ctid;
--- ctid fetched directly from the source table.
-CREATE VIEW tid_view_with_ctid AS SELECT ctid, a FROM tid_tab;
-SELECT currtid('tid_view_with_ctid'::regclass::oid, '(0,1)'::tid); -- fails
-ERROR:  tid (0, 1) is not valid for relation "tid_tab"
-SELECT currtid2('tid_view_with_ctid'::text, '(0,1)'::tid); -- fails
-ERROR:  tid (0, 1) is not valid for relation "tid_tab"
-INSERT INTO tid_tab VALUES (1);
-SELECT currtid('tid_view_with_ctid'::regclass::oid, '(0,1)'::tid); -- ok
- currtid 
----------
- (0,1)
-(1 row)
-
-SELECT currtid2('tid_view_with_ctid'::text, '(0,1)'::tid); -- ok
- currtid2 
-----------
- (0,1)
-(1 row)
-
-DROP VIEW tid_view_with_ctid;
-TRUNCATE tid_tab;
--- ctid attribute with incorrect data type
-CREATE VIEW tid_view_fake_ctid AS SELECT 1 AS ctid, 2 AS a;
-SELECT currtid('tid_view_fake_ctid'::regclass::oid, '(0,1)'::tid); -- fails
-ERROR:  ctid isn't of type TID
-SELECT currtid2('tid_view_fake_ctid'::text, '(0,1)'::tid); -- fails
-ERROR:  ctid isn't of type TID
-DROP VIEW tid_view_fake_ctid;
 DROP TABLE tid_tab CASCADE;
diff --git a/src/test/regress/sql/tid.sql b/src/test/regress/sql/tid.sql
index c0d02df34f..cbf165fa99 100644
--- a/src/test/regress/sql/tid.sql
+++ b/src/test/regress/sql/tid.sql
@@ -8,56 +8,4 @@ SELECT min(ctid) FROM tid_tab;
 SELECT max(ctid) FROM tid_tab;
 TRUNCATE tid_tab;
 
--- Tests for currtid() and currtid2() with various relation kinds
-
--- Materialized view
-CREATE MATERIALIZED VIEW tid_matview AS SELECT a FROM tid_tab;
-SELECT currtid('tid_matview'::regclass::oid, '(0,1)'::tid); -- fails
-SELECT currtid2('tid_matview'::text, '(0,1)'::tid); -- fails
-INSERT INTO tid_tab VALUES (1);
-REFRESH MATERIALIZED VIEW tid_matview;
-SELECT currtid('tid_matview'::regclass::oid, '(0,1)'::tid); -- ok
-SELECT currtid2('tid_matview'::text, '(0,1)'::tid); -- ok
-DROP MATERIALIZED VIEW tid_matview;
-TRUNCATE tid_tab;
-
--- Sequence
-CREATE SEQUENCE tid_seq;
-SELECT currtid('tid_seq'::regclass::oid, '(0,1)'::tid); -- ok
-SELECT currtid2('tid_seq'::text, '(0,1)'::tid); -- ok
-DROP SEQUENCE tid_seq;
-
--- Index, fails with incorrect relation type
-CREATE INDEX tid_ind ON tid_tab(a);
-SELECT currtid('tid_ind'::regclass::oid, '(0,1)'::tid); -- fails
-SELECT currtid2('tid_ind'::text, '(0,1)'::tid); -- fails
-DROP INDEX tid_ind;
-
--- Partitioned table, no storage
-CREATE TABLE tid_part (a int) PARTITION BY RANGE (a);
-SELECT currtid('tid_part'::regclass::oid, '(0,1)'::tid); -- fails
-SELECT currtid2('tid_part'::text, '(0,1)'::tid); -- fails
-DROP TABLE tid_part;
-
--- Views
--- ctid not defined in the view
-CREATE VIEW tid_view_no_ctid AS SELECT a FROM tid_tab;
-SELECT currtid('tid_view_no_ctid'::regclass::oid, '(0,1)'::tid); -- fails
-SELECT currtid2('tid_view_no_ctid'::text, '(0,1)'::tid); -- fails
-DROP VIEW tid_view_no_ctid;
--- ctid fetched directly from the source table.
-CREATE VIEW tid_view_with_ctid AS SELECT ctid, a FROM tid_tab;
-SELECT currtid('tid_view_with_ctid'::regclass::oid, '(0,1)'::tid); -- fails
-SELECT currtid2('tid_view_with_ctid'::text, '(0,1)'::tid); -- fails
-INSERT INTO tid_tab VALUES (1);
-SELECT currtid('tid_view_with_ctid'::regclass::oid, '(0,1)'::tid); -- ok
-SELECT currtid2('tid_view_with_ctid'::text, '(0,1)'::tid); -- ok
-DROP VIEW tid_view_with_ctid;
-TRUNCATE tid_tab;
--- ctid attribute with incorrect data type
-CREATE VIEW tid_view_fake_ctid AS SELECT 1 AS ctid, 2 AS a;
-SELECT currtid('tid_view_fake_ctid'::regclass::oid, '(0,1)'::tid); -- fails
-SELECT currtid2('tid_view_fake_ctid'::text, '(0,1)'::tid); -- fails
-DROP VIEW tid_view_fake_ctid;
-
 DROP TABLE tid_tab CASCADE;
-- 
2.28.0

Attachment: signature.asc
Description: PGP signature

Reply via email to