2929#include "utils/lsyscache.h"
3030#include "utils/numeric.h"
3131#include "utils/ruleutils.h"
32+ #include "utils/snapmgr.h"
3233#include "utils/syscache.h"
3334
3435#if PG_VERSION_NUM >=100000
@@ -72,10 +73,11 @@ static void modify_range_constraint(Oid partition_relid,
7273const Bound * lower ,
7374const Bound * upper );
7475static char * get_qualified_rel_name (Oid relid );
75- static void drop_table_by_oid (Oid relid );
76+ static void drop_table_by_oid (Oid relid , bool concurrent );
7677static bool interval_is_trivial (Oid atttype ,
7778Datum interval ,
7879Oid interval_type );
80+ static void remove_inheritance (Oid parent_relid ,Oid partition_relid );
7981
8082
8183/*
@@ -737,19 +739,25 @@ merge_range_partitions_internal(Oid parent_relid, Oid *parts, uint32 nparts)
737739prel -> ev_type ,
738740NULL ,
739741NULL );
742+
743+ /* should be invalidated */
744+ //Assert(!prel->valid);
745+
740746/* Make new relation visible */
741747CommandCounterIncrement ();
742748
743749if (SPI_connect ()!= SPI_OK_CONNECT )
744750elog (ERROR ,"could not connect using SPI" );
745751
746752/* Copy the data from all partition to the first one */
747- for (i = 1 ;i < nparts ;i ++ )
753+ for (i = 0 ;i < nparts ;i ++ )
748754{
755+ char * query ;
756+
749757/* Prevent modification on relation */
750758LockRelationOid (parts [i ],ShareLock );
751759
752- char * query = psprintf ("INSERT INTO %s SELECT * FROM %s" ,
760+ query = psprintf ("INSERT INTO %s SELECT * FROM %s" ,
753761get_qualified_rel_name (partition_relid ),
754762get_qualified_rel_name (parts [i ]));
755763
@@ -759,11 +767,22 @@ merge_range_partitions_internal(Oid parent_relid, Oid *parts, uint32 nparts)
759767
760768SPI_finish ();
761769
762- /* Drop partitions */
770+ /*
771+ * Now detach these partitions.
772+ * this would get AccessExclusiveLock.
773+ */
774+ for (i = 0 ;i < nparts ;i ++ )
775+ remove_inheritance (parent_relid ,parts [i ]);
776+
777+ /* Now we can drop the partitions */
763778for (i = 0 ;i < nparts ;i ++ )
764779{
780+ /*
781+ * we should get AccessExclusiveLock anyway, because logic of
782+ * ALTER TABLE .. NO INHERIT that we did before could change
783+ */
765784LockRelationOid (parts [i ],AccessExclusiveLock );
766- drop_table_by_oid (parts [i ]);
785+ drop_table_by_oid (parts [i ], false );
767786}
768787}
769788
@@ -825,7 +844,7 @@ drop_range_partition_expand_next(PG_FUNCTION_ARGS)
825844}
826845
827846/* Finally drop this partition */
828- drop_table_by_oid (relid );
847+ drop_table_by_oid (relid , false );
829848
830849PG_RETURN_VOID ();
831850}
@@ -1244,7 +1263,7 @@ get_qualified_rel_name(Oid relid)
12441263 * Drop table using it's Oid
12451264 */
12461265static void
1247- drop_table_by_oid (Oid relid )
1266+ drop_table_by_oid (Oid relid , bool concurrent )
12481267{
12491268DropStmt * n = makeNode (DropStmt );
12501269const char * relname = get_qualified_rel_name (relid );
@@ -1256,7 +1275,30 @@ drop_table_by_oid(Oid relid)
12561275n -> arguments = NIL ;
12571276#endif
12581277n -> behavior = DROP_RESTRICT ;/* default behavior */
1259- n -> concurrent = false ;
1278+ n -> concurrent = concurrent ;
12601279
12611280RemoveRelations (n );
12621281}
1282+
1283+ /* Remove inheritance for partition */
1284+ static void
1285+ remove_inheritance (Oid parent_relid ,Oid partition_relid )
1286+ {
1287+ AlterTableStmt * stmt = makeNode (AlterTableStmt );
1288+ AlterTableCmd * cmd = makeNode (AlterTableCmd );
1289+ LOCKMODE lockmode ;
1290+
1291+ stmt -> relation = makeRangeVarFromNameList (
1292+ stringToQualifiedNameList (get_qualified_rel_name (partition_relid )));
1293+ stmt -> relkind = OBJECT_TABLE ;
1294+ stmt -> cmds = list_make1 (cmd );
1295+ stmt -> missing_ok = false;
1296+
1297+ cmd -> subtype = AT_DropInherit ;
1298+ cmd -> def = (Node * )makeRangeVarFromNameList (
1299+ stringToQualifiedNameList (get_qualified_rel_name (parent_relid )));
1300+
1301+ lockmode = AlterTableGetLockLevel (stmt -> cmds );
1302+ LockRelationOid (partition_relid ,lockmode );
1303+ AlterTable (partition_relid ,lockmode ,stmt );
1304+ }