@@ -629,6 +629,106 @@ def test_parallel_nodes(self):
629629node .stop ()
630630node .cleanup ()
631631
632+ def test_conc_part_drop_runtime_append (self ):
633+ """ Test concurrent partition drop + SELECT (RuntimeAppend) """
634+
635+ # Create and start new instance
636+ node = self .start_new_pathman_cluster (allows_streaming = False )
637+
638+ # Create table 'drop_test' and partition it
639+ with node .connect ()as con0 :
640+ # yapf: disable
641+ con0 .begin ()
642+ con0 .execute ("create table drop_test(val int not null)" )
643+ con0 .execute ("insert into drop_test select generate_series(1, 1000)" )
644+ con0 .execute ("select create_range_partitions('drop_test', 'val', 1, 10)" )
645+ con0 .commit ()
646+
647+ # Create two separate connections for this test
648+ with node .connect ()as con1 ,node .connect ()as con2 :
649+
650+ # Thread for connection #2 (it has to wait)
651+ def con2_thread ():
652+ con1 .begin ()
653+ con2 .execute ('set enable_hashjoin = f' )
654+ con2 .execute ('set enable_mergejoin = f' )
655+
656+ res = con2 .execute ("""
657+ explain (analyze, costs off, timing off)
658+ select * from drop_test
659+ where val = any (select generate_series(1, 40, 34))
660+ """ )# query selects from drop_test_1 and drop_test_4
661+
662+ con2 .commit ()
663+
664+ has_runtime_append = False
665+ has_drop_test_1 = False
666+ has_drop_test_4 = False
667+
668+ for row in res :
669+ if row [0 ].find ('RuntimeAppend' )>= 0 :
670+ has_runtime_append = True
671+ continue
672+
673+ if row [0 ].find ('drop_test_1' )>= 0 :
674+ has_drop_test_1 = True
675+ continue
676+
677+ if row [0 ].find ('drop_test_4' )>= 0 :
678+ has_drop_test_4 = True
679+ continue
680+
681+ self .assertTrue (has_runtime_append )
682+ self .assertFalse (has_drop_test_1 )
683+ self .assertTrue (has_drop_test_4 )
684+
685+ # Step 1: cache partitioned table in con1
686+ con1 .begin ()
687+ con1 .execute ('select count(*) from drop_test' )# load pathman's cache
688+ con1 .commit ()
689+
690+ # Step 2: cache partitioned table in con2
691+ con2 .begin ()
692+ con2 .execute ('select count(*) from drop_test' )# load pathman's cache
693+ con2 .commit ()
694+
695+ # Step 3: drop first partition of 'drop_test'
696+ con1 .begin ()
697+ con1 .execute ('drop table drop_test_1' )
698+
699+ # Step 4: try executing select (RuntimeAppend)
700+ t = threading .Thread (target = con2_thread )
701+ t .start ()
702+
703+ # Step 5: wait until 't' locks
704+ while True :
705+ with node .connect ()as con0 :
706+ locks = con0 .execute ("""
707+ select count(*) from pg_locks where granted = 'f'
708+ """ )
709+
710+ if int (locks [0 ][0 ])> 0 :
711+ break
712+
713+ # Step 6: commit 'DROP TABLE'
714+ con1 .commit ()
715+
716+ # Step 7: wait for con2
717+ t .join ()
718+
719+ rows = con1 .execute ("""
720+ select * from pathman_partition_list
721+ where parent = 'drop_test'::regclass
722+ order by range_min, range_max
723+ """ )
724+
725+ # check number of partitions
726+ self .assertEqual (len (rows ),99 )
727+
728+ # Stop instance and finish work
729+ node .stop ()
730+ node .cleanup ()
731+
632732def test_conc_part_creation_insert (self ):
633733""" Test concurrent partition creation on INSERT """
634734