Hi!

Now it looks good for me.  I'm marking it "Ready for committer".

I have a question: why do not CheckForSerializableConflictIn() move into begining of gistplacetopage()? Seems, it is the single function which actually changes page and all predicate locking stuff will be placed in single function...

See attached version of patch.
--
Teodor Sigaev                                   E-mail: teo...@sigaev.ru
                                                   WWW: http://www.sigaev.ru/
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 51c32e4afe..5ee1e5e4e1 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -18,6 +18,8 @@
 #include "access/gistscan.h"
 #include "catalog/pg_collation.h"
 #include "miscadmin.h"
+#include "storage/lmgr.h"
+#include "storage/predicate.h"
 #include "nodes/execnodes.h"
 #include "utils/builtins.h"
 #include "utils/index_selfuncs.h"
@@ -70,7 +72,7 @@ gisthandler(PG_FUNCTION_ARGS)
 	amroutine->amsearchnulls = true;
 	amroutine->amstorage = true;
 	amroutine->amclusterable = true;
-	amroutine->ampredlocks = false;
+	amroutine->ampredlocks = true;
 	amroutine->amcanparallel = false;
 	amroutine->amkeytype = InvalidOid;
 
@@ -224,6 +226,12 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 	int			i;
 	bool		is_split;
 
+	/*
+	 * Check for any rw conflicts (in serialisation isolation level)
+	 * just before we intend to modify the page
+	 */
+	CheckForSerializableConflictIn(rel, NULL, buffer);
+
 	/*
 	 * Refuse to modify a page that's incompletely split. This should not
 	 * happen because we finish any incomplete splits while we walk down the
@@ -446,6 +454,11 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 			GistPageSetNSN(ptr->page, oldnsn);
 		}
 
+		for (ptr = dist; ptr; ptr = ptr->next)
+			PredicateLockPageSplit(rel,
+						BufferGetBlockNumber(buffer),
+						BufferGetBlockNumber(ptr->buffer));
+
 		/*
 		 * gistXLogSplit() needs to WAL log a lot of pages, prepare WAL
 		 * insertion for that. NB: The number of pages and data segments
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index b30b931c3b..c4e8a3b913 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -18,6 +18,8 @@
 #include "access/relscan.h"
 #include "catalog/pg_type.h"
 #include "miscadmin.h"
+#include "storage/lmgr.h"
+#include "storage/predicate.h"
 #include "pgstat.h"
 #include "lib/pairingheap.h"
 #include "utils/builtins.h"
@@ -336,6 +338,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
 
 	buffer = ReadBuffer(scan->indexRelation, pageItem->blkno);
 	LockBuffer(buffer, GIST_SHARE);
+	PredicateLockPage(r, BufferGetBlockNumber(buffer), scan->xs_snapshot);
 	gistcheckpage(scan->indexRelation, buffer);
 	page = BufferGetPage(buffer);
 	TestForOldSnapshot(scan->xs_snapshot, r, page);
diff --git a/src/backend/storage/lmgr/README-SSI b/src/backend/storage/lmgr/README-SSI
index a9dc01f237..e221241f96 100644
--- a/src/backend/storage/lmgr/README-SSI
+++ b/src/backend/storage/lmgr/README-SSI
@@ -374,10 +374,11 @@ however, a search discovers that no root page has yet been created, a
 predicate lock on the index relation is required.
 
     * GiST searches can determine that there are no matches at any
-level of the index, so there must be a predicate lock at each index
+level of the index, so we acquire predicate lock at each index
 level during a GiST search. An index insert at the leaf level can
 then be trusted to ripple up to all levels and locations where
-conflicting predicate locks may exist.
+conflicting predicate locks may exist. In case there is a page split,
+we need to copy predicate lock from an original page to all new pages.
 
     * The effects of page splits, overflows, consolidations, and
 removals must be carefully reviewed to ensure that predicate locks
diff --git a/src/test/isolation/expected/predicate-gist.out b/src/test/isolation/expected/predicate-gist.out
new file mode 100644
index 0000000000..77a27958af
--- /dev/null
+++ b/src/test/isolation/expected/predicate-gist.out
@@ -0,0 +1,659 @@
+Parsed test spec with 2 sessions
+
+starting permutation: rxy1 wx1 c1 rxy2 wy2 c2
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step c1: commit;
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2233750        
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step c2: commit;
+
+starting permutation: rxy2 wy2 c2 rxy1 wx1 c1
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step c2: commit;
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+316250         
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step c1: commit;
+
+starting permutation: rxy3 wx3 c1 rxy4 wy4 c2
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c1: commit;
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c2: commit;
+
+starting permutation: rxy4 wy4 c2 rxy3 wx3 c1
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c2: commit;
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c1: commit;
+
+starting permutation: rxy1 wx1 rxy2 c1 wy2 c2
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step c1: commit;
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+step c2: commit;
+
+starting permutation: rxy1 wx1 rxy2 wy2 c1 c2
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step c1: commit;
+step c2: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 wx1 rxy2 wy2 c2 c1
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step c2: commit;
+step c1: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 rxy2 wx1 c1 wy2 c2
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step c1: commit;
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+step c2: commit;
+
+starting permutation: rxy1 rxy2 wx1 wy2 c1 c2
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step c1: commit;
+step c2: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 rxy2 wx1 wy2 c2 c1
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step c2: commit;
+step c1: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 rxy2 wy2 wx1 c1 c2
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step c1: commit;
+step c2: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 rxy2 wy2 wx1 c2 c1
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step c2: commit;
+step c1: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy1 rxy2 wy2 c2 wx1 c1
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step c2: commit;
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+step c1: commit;
+
+starting permutation: rxy2 rxy1 wx1 c1 wy2 c2
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step c1: commit;
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+step c2: commit;
+
+starting permutation: rxy2 rxy1 wx1 wy2 c1 c2
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step c1: commit;
+step c2: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 rxy1 wx1 wy2 c2 c1
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step c2: commit;
+step c1: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 rxy1 wy2 wx1 c1 c2
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step c1: commit;
+step c2: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 rxy1 wy2 wx1 c2 c1
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step c2: commit;
+step c1: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 rxy1 wy2 c2 wx1 c1
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step c2: commit;
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+step c1: commit;
+
+starting permutation: rxy2 wy2 rxy1 wx1 c1 c2
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step c1: commit;
+step c2: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 wy2 rxy1 wx1 c2 c1
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+step c2: commit;
+step c1: commit;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+
+starting permutation: rxy2 wy2 rxy1 c2 wx1 c1
+step rxy2: select sum(p[0]) from gist_point_tbl where p >> point(7500,7500);
+sum            
+
+2188750        
+step wy2: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g;
+step rxy1: select sum(p[0]) from gist_point_tbl where p << point(2500, 2500);
+sum            
+
+311250         
+step c2: commit;
+step wx1: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g;
+ERROR:  could not serialize access due to read/write dependencies among transactions
+step c1: commit;
+
+starting permutation: rxy3 wx3 rxy4 c1 wy4 c2
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step c1: commit;
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c2: commit;
+
+starting permutation: rxy3 wx3 rxy4 wy4 c1 c2
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy3 wx3 rxy4 wy4 c2 c1
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy3 rxy4 wx3 c1 wy4 c2
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c1: commit;
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c2: commit;
+
+starting permutation: rxy3 rxy4 wx3 wy4 c1 c2
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy3 rxy4 wx3 wy4 c2 c1
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy3 rxy4 wy4 wx3 c1 c2
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy3 rxy4 wy4 wx3 c2 c1
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy3 rxy4 wy4 c2 wx3 c1
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c2: commit;
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c1: commit;
+
+starting permutation: rxy4 rxy3 wx3 c1 wy4 c2
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c1: commit;
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c2: commit;
+
+starting permutation: rxy4 rxy3 wx3 wy4 c1 c2
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy4 rxy3 wx3 wy4 c2 c1
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy4 rxy3 wy4 wx3 c1 c2
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy4 rxy3 wy4 wx3 c2 c1
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy4 rxy3 wy4 c2 wx3 c1
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step c2: commit;
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c1: commit;
+
+starting permutation: rxy4 wy4 rxy3 wx3 c1 c2
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c1: commit;
+step c2: commit;
+
+starting permutation: rxy4 wy4 rxy3 wx3 c2 c1
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c2: commit;
+step c1: commit;
+
+starting permutation: rxy4 wy4 rxy3 c2 wx3 c1
+step rxy4: select sum(p[0]) from gist_point_tbl where p << point(1000,1000);
+sum            
+
+49500          
+step wy4: insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g;
+step rxy3: select sum(p[0]) from gist_point_tbl where p >> point(6000,6000);
+sum            
+
+3202000        
+step c2: commit;
+step wx3: insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g;
+step c1: commit;
diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule
index 74d7d59546..53e1f192b0 100644
--- a/src/test/isolation/isolation_schedule
+++ b/src/test/isolation/isolation_schedule
@@ -66,3 +66,4 @@ test: async-notify
 test: vacuum-reltuples
 test: timeouts
 test: vacuum-concurrent-drop
+test: predicate-gist
diff --git a/src/test/isolation/specs/predicate-gist.spec b/src/test/isolation/specs/predicate-gist.spec
new file mode 100644
index 0000000000..a5d3f6456f
--- /dev/null
+++ b/src/test/isolation/specs/predicate-gist.spec
@@ -0,0 +1,117 @@
+# Test for page level predicate locking in gist
+#
+# Test to verify serialization failures and to check reduced false positives
+#
+# To verify serialization failures, queries and permutations are written in such
+# a way that an index scan  (from one transaction) and an index insert (from
+# another transaction) will try to access the same part (sub-tree) of the index
+# whereas to check reduced false positives, they will try to access different
+# parts (sub-tree) of the index.
+
+setup
+{
+  create table gist_point_tbl(id int4, p point);
+  create index gist_pointidx on gist_point_tbl using gist(p);
+  insert into gist_point_tbl (id, p)
+  select g, point(g*10, g*10) from generate_series(1, 1000) g;
+}
+
+teardown
+{
+  drop table gist_point_tbl;
+}
+
+session "s1"
+setup
+{
+  begin isolation level serializable;
+  set enable_seqscan=off;
+  set enable_bitmapscan=off;
+  set enable_indexonlyscan=on;
+}
+
+step "rxy1"	{ select sum(p[0]) from gist_point_tbl where p << point(2500, 2500); }
+step "wx1"	{ insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(15, 20) g; }
+step "rxy3"	{ select sum(p[0]) from gist_point_tbl where p >> point(6000,6000); }
+step "wx3"	{ insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(12, 18) g; }
+step "c1"	{ commit; }
+
+
+session "s2"
+setup
+{
+  begin isolation level serializable;
+  set enable_seqscan=off;
+  set enable_bitmapscan=off;
+  set enable_indexonlyscan=on;
+}
+
+step "rxy2"	{ select sum(p[0]) from gist_point_tbl where p >> point(7500,7500); }
+step "wy2"	{ insert into gist_point_tbl (id, p)
+			  select g, point(g*500, g*500) from generate_series(1, 5) g; }
+step "rxy4"	{ select sum(p[0]) from gist_point_tbl where p << point(1000,1000); }
+step "wy4"	{ insert into gist_point_tbl (id, p)
+			  select g, point(g*50, g*50) from generate_series(1, 20) g; }
+step "c2"	{ commit; }
+
+# An index scan (from one transaction) and an index insert (from another
+# transaction) try to access the same part of the index but one transaction
+# commits before other transaction begins so no r-w conflict.
+
+permutation "rxy1" "wx1" "c1" "rxy2" "wy2" "c2"
+permutation "rxy2" "wy2" "c2" "rxy1" "wx1" "c1"
+
+# An index scan (from one transaction) and an index insert (from another
+# transaction) try to access different parts of the index and also one
+# transaction commits before other transaction begins, so no r-w conflict.
+
+permutation "rxy3" "wx3" "c1" "rxy4" "wy4" "c2"
+permutation "rxy4" "wy4" "c2" "rxy3" "wx3" "c1"
+
+
+# An index scan (from one transaction) and an index insert (from another 
+# transaction) try to access the same part of the index and one transaction 
+# begins before other transaction commits so there is a r-w conflict.
+
+permutation "rxy1" "wx1" "rxy2" "c1" "wy2" "c2"
+permutation "rxy1" "wx1" "rxy2" "wy2" "c1" "c2"
+permutation "rxy1" "wx1" "rxy2" "wy2" "c2" "c1"
+permutation "rxy1" "rxy2" "wx1" "c1" "wy2" "c2"
+permutation "rxy1" "rxy2" "wx1" "wy2" "c1" "c2"
+permutation "rxy1" "rxy2" "wx1" "wy2" "c2" "c1"
+permutation "rxy1" "rxy2" "wy2" "wx1" "c1" "c2"
+permutation "rxy1" "rxy2" "wy2" "wx1" "c2" "c1"
+permutation "rxy1" "rxy2" "wy2" "c2" "wx1" "c1"
+permutation "rxy2" "rxy1" "wx1" "c1" "wy2" "c2"
+permutation "rxy2" "rxy1" "wx1" "wy2" "c1" "c2"
+permutation "rxy2" "rxy1" "wx1" "wy2" "c2" "c1"
+permutation "rxy2" "rxy1" "wy2" "wx1" "c1" "c2"
+permutation "rxy2" "rxy1" "wy2" "wx1" "c2" "c1"
+permutation "rxy2" "rxy1" "wy2" "c2" "wx1" "c1"
+permutation "rxy2" "wy2" "rxy1" "wx1" "c1" "c2"
+permutation "rxy2" "wy2" "rxy1" "wx1" "c2" "c1"
+permutation "rxy2" "wy2" "rxy1" "c2" "wx1" "c1"
+
+# An index scan (from one transaction) and an index insert (from another 
+# transaction) try to access different parts of the index so no r-w conflict.
+
+permutation "rxy3" "wx3" "rxy4" "c1" "wy4" "c2"
+permutation "rxy3" "wx3" "rxy4" "wy4" "c1" "c2"
+permutation "rxy3" "wx3" "rxy4" "wy4" "c2" "c1"
+permutation "rxy3" "rxy4" "wx3" "c1" "wy4" "c2"
+permutation "rxy3" "rxy4" "wx3" "wy4" "c1" "c2"
+permutation "rxy3" "rxy4" "wx3" "wy4" "c2" "c1"
+permutation "rxy3" "rxy4" "wy4" "wx3" "c1" "c2"
+permutation "rxy3" "rxy4" "wy4" "wx3" "c2" "c1"
+permutation "rxy3" "rxy4" "wy4" "c2" "wx3" "c1"
+permutation "rxy4" "rxy3" "wx3" "c1" "wy4" "c2"
+permutation "rxy4" "rxy3" "wx3" "wy4" "c1" "c2"
+permutation "rxy4" "rxy3" "wx3" "wy4" "c2" "c1"
+permutation "rxy4" "rxy3" "wy4" "wx3" "c1" "c2"
+permutation "rxy4" "rxy3" "wy4" "wx3" "c2" "c1"
+permutation "rxy4" "rxy3" "wy4" "c2" "wx3" "c1"
+permutation "rxy4" "wy4" "rxy3" "wx3" "c1" "c2"
+permutation "rxy4" "wy4" "rxy3" "wx3" "c2" "c1"
+permutation "rxy4" "wy4" "rxy3" "c2" "wx3" "c1"

Reply via email to