From 56bd50a63afc4c2c3f31f26a0411bf22c54bbb6f Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Tue, 9 Apr 2019 15:36:59 +0300
Subject: [PATCH 3/4] Add test for bug with index reorder queue slot type
 confusion.

This currently fails an assertion.
---
 src/test/modules/toytable/Makefile            |  2 +-
 .../toytable/expected/index-reorder-slot.out  | 25 ++++++++++++
 .../toytable/sql/index-reorder-slot.sql       | 15 +++++++
 src/test/modules/toytable/toytableam.c        | 40 ++++++++++++++++---
 4 files changed, 76 insertions(+), 6 deletions(-)
 create mode 100644 src/test/modules/toytable/expected/index-reorder-slot.out
 create mode 100644 src/test/modules/toytable/sql/index-reorder-slot.sql

diff --git a/src/test/modules/toytable/Makefile b/src/test/modules/toytable/Makefile
index 142ef2d23e6..a763ddacc89 100644
--- a/src/test/modules/toytable/Makefile
+++ b/src/test/modules/toytable/Makefile
@@ -7,7 +7,7 @@ PGFILEDESC = "A dummy implementantation of the table AM API"
 EXTENSION = toytable
 DATA = toytable--1.0.sql
 
-REGRESS = toytable
+REGRESS = toytable index-reorder-slot
 
 ifdef USE_PGXS
 PG_CONFIG = pg_config
diff --git a/src/test/modules/toytable/expected/index-reorder-slot.out b/src/test/modules/toytable/expected/index-reorder-slot.out
new file mode 100644
index 00000000000..52a1ccec850
--- /dev/null
+++ b/src/test/modules/toytable/expected/index-reorder-slot.out
@@ -0,0 +1,25 @@
+create extension toytable;
+ERROR:  extension "toytable" already exists
+set toytable.num_tuples = 10000;
+-- This is a variant of the test in 'polygon' regression test, but using
+-- the toy table. It used to fail an assertion, because index scan would
+-- sometimes use the reorderqueue's slot, which is a heaptuple slot, and
+-- sometimes the table's scan slot, which is a virtual slot with toytable
+CREATE TABLE quad_poly_toy (id int, p polygon) USING toytable;
+CREATE INDEX quad_poly_toy_idx ON quad_poly_toy USING spgist(p);
+set enable_seqscan=off;
+SELECT * FROM quad_poly_toy ORDER BY p <-> point '123,456' LIMIT 10;
+ id  |           p           
+-----+-----------------------
+ 284 | ((284,284),(294,294))
+ 283 | ((283,283),(293,293))
+ 287 | ((287,287),(297,297))
+ 286 | ((286,286),(296,296))
+ 280 | ((280,280),(290,290))
+ 289 | ((289,289),(299,299))
+ 288 | ((288,288),(298,298))
+ 285 | ((285,285),(295,295))
+ 281 | ((281,281),(291,291))
+ 282 | ((282,282),(292,292))
+(10 rows)
+
diff --git a/src/test/modules/toytable/sql/index-reorder-slot.sql b/src/test/modules/toytable/sql/index-reorder-slot.sql
new file mode 100644
index 00000000000..7154639aa27
--- /dev/null
+++ b/src/test/modules/toytable/sql/index-reorder-slot.sql
@@ -0,0 +1,15 @@
+create extension toytable;
+
+set toytable.num_tuples = 10000;
+
+-- This is a variant of the test in 'polygon' regression test, but using
+-- the toy table. It used to fail an assertion, because index scan would
+-- sometimes use the reorderqueue's slot, which is a heaptuple slot, and
+-- sometimes the table's scan slot, which is a virtual slot with toytable
+CREATE TABLE quad_poly_toy (id int, p polygon) USING toytable;
+
+CREATE INDEX quad_poly_toy_idx ON quad_poly_toy USING spgist(p);
+
+set enable_seqscan=off;
+
+SELECT * FROM quad_poly_toy ORDER BY p <-> point '123,456' LIMIT 10;
diff --git a/src/test/modules/toytable/toytableam.c b/src/test/modules/toytable/toytableam.c
index 4cb2b5d75db..35ce6ce4709 100644
--- a/src/test/modules/toytable/toytableam.c
+++ b/src/test/modules/toytable/toytableam.c
@@ -30,10 +30,39 @@
 #include "utils/rel.h"
 #include "storage/bufmgr.h"
 
+/*
+ * Number of rows the fake table data will include.
+ * Can be set with the toytable.num_tuples GUC.
+ */
+int num_toy_tuples;
+
 PG_MODULE_MAGIC;
 
 PG_FUNCTION_INFO_V1(toytableam_handler);
 
+void _PG_init(void);
+
+
+/*
+ * Module Load Callback
+ */
+void
+_PG_init(void)
+{
+	/* Define custom GUC variables */
+	DefineCustomIntVariable("toytable.num_tuples",
+							"Number of tuples the in the fake table data",
+							NULL,
+							&num_toy_tuples,
+							10,
+							0, INT_MAX / 1000,
+							PGC_USERSET,
+							0,
+							NULL,
+							NULL,
+							NULL);
+}
+
 typedef struct
 {
 	TableScanDescData scan;
@@ -109,13 +138,14 @@ invent_toy_data(Oid atttypid, int idx, bool *isnull_p)
 		case BOXOID:
 			d = DirectFunctionCall1(box_in,
 									CStringGetDatum(psprintf("(%d,%d),(%d,%d)",
-															 idx - 10, idx - 10, idx+10, idx+10)));
+															 idx, idx, idx+10, idx+10)));
 			isnull = false;
 			break;
 
 		case POLYGONOID:
 			d = DirectFunctionCall1(poly_in,
-									CStringGetDatum(psprintf("%d,%d,%d,%d", 0,0, idx, idx)));
+									CStringGetDatum(psprintf("%d,%d,%d,%d",
+															 idx,idx, idx+10, idx+10)));
 			isnull = false;
 			break;
 
@@ -143,7 +173,7 @@ toyam_scan_getnextslot(TableScanDesc scan,
 	 * Return a constant 1 rows. Every int4 attribute gets
 	 * a running count, everything else is NULL.
 	 */
-	if (tscan->tupidx < 10)
+	if (tscan->tupidx < num_toy_tuples)
 	{
 		TupleDesc desc = RelationGetDescr(tscan->scan.rs_rd);
 
@@ -232,7 +262,7 @@ toyam_index_fetch_tuple(struct IndexFetchTableData *scan,
 		return false;
 
 	tupidx = ItemPointerGetOffsetNumber(tid);
-	if (tupidx < 1 || tupidx > 10)
+	if (tupidx < 1 || tupidx > num_toy_tuples)
 		return false;
 
 	slot->tts_nvalid = 0;
@@ -527,7 +557,7 @@ toyam_index_build_range_scan(Relation heap_rel,
 	ExecDropSingleTupleTableSlot(slot);
 	FreeExecutorState(estate);
 
-	return 10;
+	return num_toy_tuples;
 }
 
 static void
-- 
2.20.1

