@@ -629,6 +629,106 @@ def test_parallel_nodes(self):
629
629
node .stop ()
630
630
node .cleanup ()
631
631
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
+
632
732
def test_conc_part_creation_insert (self ):
633
733
""" Test concurrent partition creation on INSERT """
634
734
0 commit comments