>From 86d867084e6c44f9d7c732f2e315b4dcd34fd711 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Thu, 6 Aug 2015 21:15:08 +0900
Subject: [PATCH 6/6] Use modified index of pg_mvcoefficient.

Add column vector to the index of pg_mvcoefficient and make use of it
on DDL operation.
---
 src/backend/commands/tablecmds.c | 74 ++++++++++++++--------------------------
 src/include/catalog/indexing.h   |  2 +-
 2 files changed, 27 insertions(+), 49 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 843a14e..dd37aa8 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -9327,9 +9327,11 @@ ATExecAddDropMvStatistics(Relation rel, List * params, bool drop)
 	Oid			relid = RelationGetRelid(rel);
 	int			ncols = 0;
 	int16		colids[MVCOEF_MAX_COLS];
+	int2vector *colvec = NULL;
 	Relation 	mvcrel;
 	HeapTuple	oldtup, newtup;
-	ScanKeyData	scankey;
+	int			nscankeys;
+	ScanKeyData	scankey[2];
 	SysScanDesc	sysscan;
 	Datum	values[Natts_pg_mvcoefficient];
 	bool	nulls[Natts_pg_mvcoefficient];
@@ -9395,62 +9397,38 @@ ATExecAddDropMvStatistics(Relation rel, List * params, bool drop)
 
 	mvcrel = heap_open(MvCoefficientRelationId, RowExclusiveLock);
 
-	ScanKeyInit(&scankey,
+	nscankeys = 1;
+	ScanKeyInit(&scankey[0],
 				Anum_pg_mvcoefficient_mvcreloid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(relid));
-	sysscan = systable_beginscan(mvcrel, MvCoefficientIndexId, true,
-								 NULL, 1, &scankey);
-
-	/* colum list is required to be sorted in comparison */
-	qsort(colids, ncols, sizeof(int16), cmpint16);
+	if (ncols > 0)
+	{
+		qsort(colids, ncols, sizeof(int16), cmpint16);
+		colvec = buildint2vector(colids, ncols);
 
+		ScanKeyInit(&scankey[1],
+					Anum_pg_mvcoefficient_mvcattrs,
+					BTEqualStrategyNumber, F_INT2VECTOREQ,
+					PointerGetDatum(colvec));
+		nscankeys = 2;
+	}
+	sysscan = systable_beginscan(mvcrel, MvCoefficientIndexId, true,
+								 NULL, nscankeys, scankey);
 	if (drop)
 	{
-		bool dropped = false;
-
+		/* Two or more tuples may be returned for the drop case */
 		while (HeapTupleIsValid(oldtup = systable_getnext(sysscan)))
 		{
-			Form_pg_mvcoefficient mvc =
-				(Form_pg_mvcoefficient) GETSTRUCT (oldtup);
-			int i;
-
-			/* Fast exit, number of columns don't match  */
-			if (mvc->mvcnattrs != ncols)
-				continue;
-
-			/*
-			 * Check for individual columns. This assumes that both of the
-			 * column vector in mvc and colids are sorted.
-			 */
-			for (i = 0 ; i < ncols ; i++)
-			{
-				if (mvc->mvcattrs.values[i] != colids[i])
-					break;
-			}
-
-			/*
-			 * Remove it if match. Unconditionally do this for the case of
-			 * ncols == 0.
-			 */
-			if (i == ncols)
-			{
-				simple_heap_delete(mvcrel, &oldtup->t_self);
-				dropped = true;
-			}
+			simple_heap_delete(mvcrel, &oldtup->t_self);
 		}
-
-		if (!dropped)
-			ereport(ERROR,
-					(errcode(ERRCODE_NO_DATA_FOUND),
-					 errmsg("no matching statistics found")));
 	}
 	else
 	{
-		int2vector *colvec;
-
+		/* At most one tuple is fetched for the add case */
 		oldtup = systable_getnext(sysscan);
 
+		/* Create data for the new tuple */
 		for (i = 0; i < Natts_pg_mvcoefficient ; ++i)
 		{
 			nulls[i] = false;
@@ -9458,8 +9436,7 @@ ATExecAddDropMvStatistics(Relation rel, List * params, bool drop)
 			replaces[i] = false;
 		}
 
-		colvec = buildint2vector(colids, ncols);
-
+		Assert(colvec != NULL);
 		values[Anum_pg_mvcoefficient_mvcreloid - 1] = ObjectIdGetDatum(relid);
 		values[Anum_pg_mvcoefficient_mvcnattrs - 1] = Int16GetDatum(ncols);
 		values[Anum_pg_mvcoefficient_mvccoefficient - 1]  = Float8GetDatum(1.0);
@@ -9467,6 +9444,7 @@ ATExecAddDropMvStatistics(Relation rel, List * params, bool drop)
 
 		if (HeapTupleIsValid(oldtup))
 		{
+			/* Update existing tuple */
 			replaces[Anum_pg_mvcoefficient_mvcnattrs - 1] = true;
 			replaces[Anum_pg_mvcoefficient_mvccoefficient - 1] = true;
 			replaces[Anum_pg_mvcoefficient_mvcattrs - 1] = true;
@@ -9480,14 +9458,14 @@ ATExecAddDropMvStatistics(Relation rel, List * params, bool drop)
 		}
 		else
 		{
-			newtup = heap_form_tuple(RelationGetDescr(mvcrel), values, nulls);
+			/* Insert new tuple  */
+			newtup = heap_form_tuple(RelationGetDescr(mvcrel),
+									 values, nulls);
 			simple_heap_insert(mvcrel, newtup);
 		}
 		CatalogUpdateIndexes(mvcrel, newtup);
 	}
-
 	systable_endscan(sysscan);
-
 	heap_close(mvcrel, RowExclusiveLock);
 }
 
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index fb28747..16ad43d 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -173,7 +173,7 @@ DECLARE_UNIQUE_INDEX(pg_largeobject_loid_pn_index, 2683, on pg_largeobject using
 DECLARE_UNIQUE_INDEX(pg_largeobject_metadata_oid_index, 2996, on pg_largeobject_metadata using btree(oid oid_ops));
 #define LargeObjectMetadataOidIndexId	2996
 
-DECLARE_UNIQUE_INDEX(pg_mvcoefficient_index, 3578, on pg_mvcoefficient using btree(mvcreloid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_mvcoefficient_index, 3578, on pg_mvcoefficient using btree(mvcreloid oid_ops, mvcattrs int2vector_ops));
 #define MvCoefficientIndexId  3578
 
 DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, on pg_namespace using btree(nspname name_ops));
-- 
1.8.3.1

