@@ -72,6 +72,10 @@ static void modify_range_constraint(Oid partition_relid,
72
72
const Bound * upper );
73
73
static char * get_qualified_rel_name (Oid relid );
74
74
static void drop_table_by_oid (Oid relid );
75
+ static Oid split_range_partitions_internal (Oid parent , Oid partition ,
76
+ Datum value , Oid value_type ,
77
+ RangeVar * new_partition_rv ,
78
+ char * new_partition_ts );
75
79
static bool interval_is_trivial (Oid atttype ,
76
80
Datum interval ,
77
81
Oid interval_type );
@@ -787,34 +791,36 @@ merge_range_partitions_internal(Oid parent, Oid *parts, uint32 nparts)
787
791
Datum
788
792
split_range_partitions (PG_FUNCTION_ARGS )
789
793
{
790
- Oid partition = PG_GETARG_OID (0 );
791
- Datum value = PG_GETARG_DATUM (1 );
792
- Oid value_type = get_fn_expr_argtype (fcinfo -> flinfo , 1 );
793
- Oid new_partition ;
794
+ Oid parent_relid ,
795
+ partition_relid ,
796
+ new_partition_relid ;
797
+ Datum value ;
798
+ Oid value_type ;
794
799
795
800
/* Optional: name & tablespace */
796
801
RangeVar * new_partition_rv = NULL ;
797
- char * new_partition_ts = NULL ;
802
+ char * new_partition_ts ;
798
803
799
- const PartRelationInfo * prel ;
800
- Oid parent ;
801
- Oid expr_type ;
802
- char * expr_cstr ;
803
- RangeEntry * rentry = NULL ;
804
- FmgrInfo cmp_finfo ;
805
- Bound fake_value_bound ;
806
- RangeEntry * ranges ;
807
- Bound min , max ;
808
-
809
- List * ri_constr ,
810
- * ri_relids ;
811
- char * bound ;
812
- int i ;
813
804
PartParentSearch parent_search ;
814
805
815
- // AttrNumber attnum;
816
- char * query ;
806
+ /* Partition's oid */
807
+ if (!PG_ARGISNULL (0 ))
808
+ {
809
+ partition_relid = PG_GETARG_OID (0 );
810
+ }
811
+ else ereport (ERROR , (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
812
+ errmsg ("'partition_relid' should not be NULL" )));
813
+
814
+ /* Split value */
815
+ if (!PG_ARGISNULL (1 ))
816
+ {
817
+ value = PG_GETARG_DATUM (1 );
818
+ value_type = get_fn_expr_argtype (fcinfo -> flinfo , 1 );
819
+ }
820
+ else ereport (ERROR , (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
821
+ errmsg ("'value' should not be NULL" )));
817
822
823
+ /* New partition's name (optional) */
818
824
if (!PG_ARGISNULL (2 ))
819
825
{
820
826
List * qualified_name ;
@@ -825,14 +831,54 @@ split_range_partitions(PG_FUNCTION_ARGS)
825
831
new_partition_rv = makeRangeVarFromNameList (qualified_name );
826
832
}
827
833
828
- if (!PG_ARGISNULL (3 ))
829
- new_partition_ts = TextDatumGetCString (PG_GETARG_TEXT_P (3 ));
834
+ /* New partition's tablesplace (optional) */
835
+ new_partition_ts = !PG_ARGISNULL (3 ) ?
836
+ TextDatumGetCString (PG_GETARG_TEXT_P (3 )) :
837
+ NULL ;
830
838
831
839
/* Get parent's relid */
832
- parent = get_parent_of_partition (partition , & parent_search );
840
+ parent_relid = get_parent_of_partition (partition_relid , & parent_search );
833
841
if (parent_search != PPS_ENTRY_PART_PARENT )
834
842
elog (ERROR , "relation \"%s\" is not a partition" ,
835
- get_rel_name_or_relid (partition ));
843
+ get_rel_name_or_relid (partition_relid ));
844
+
845
+ /* Perform split */
846
+ new_partition_relid = split_range_partitions_internal (parent_relid ,
847
+ partition_relid ,
848
+ value ,
849
+ value_type ,
850
+ new_partition_rv ,
851
+ new_partition_ts );
852
+
853
+ PG_RETURN_OID (new_partition_relid );
854
+ }
855
+
856
+ static Oid
857
+ split_range_partitions_internal (Oid parent , Oid partition ,
858
+ Datum value , Oid value_type ,
859
+ RangeVar * new_partition_rv ,
860
+ char * new_partition_ts )
861
+ {
862
+ const PartRelationInfo * prel ;
863
+ Oid expr_type ;
864
+ char * expr_cstr ;
865
+ Oid collid ;
866
+
867
+ RangeEntry * ranges ,
868
+ * rentry = NULL ;
869
+
870
+ FmgrInfo cmp_finfo ;
871
+ Bound min ,
872
+ max ,
873
+ fake_value_bound ;
874
+
875
+ Oid new_partition ;
876
+ List * ri_constr ,
877
+ * ri_relids ;
878
+ char * bound ;
879
+ int i ;
880
+
881
+ char * query ;
836
882
837
883
/* Lock parent and partition */
838
884
prevent_relation_modification_internal (partition );
@@ -846,6 +892,7 @@ split_range_partitions(PG_FUNCTION_ARGS)
846
892
ranges = PrelGetRangesArray (prel );
847
893
expr_cstr = pstrdup (prel -> expr_cstr );
848
894
expr_type = prel -> ev_type ;
895
+ collid = prel -> ev_collid ;
849
896
850
897
/* Look for the specified partition's range */
851
898
for (i = 0 ; i < PrelChildrenCount (prel ); i ++ )
@@ -860,11 +907,15 @@ split_range_partitions(PG_FUNCTION_ARGS)
860
907
min = CopyBound (& rentry -> min , prel -> ev_byval , prel -> ev_len );
861
908
max = CopyBound (& rentry -> max , prel -> ev_byval , prel -> ev_len );
862
909
863
- /* Ensure that value belongs to the range */
864
910
fill_type_cmp_fmgr_info (& cmp_finfo , expr_type , expr_type );
865
- fake_value_bound = MakeBound (perform_type_cast (value , value_type , expr_type , NULL ));
866
- if (cmp_bounds (& cmp_finfo , prel -> ev_collid , & fake_value_bound , & min ) < 0
867
- || cmp_bounds (& cmp_finfo , prel -> ev_collid , & fake_value_bound , & max ) >= 0 )
911
+ fake_value_bound = MakeBound (perform_type_cast (value ,
912
+ value_type ,
913
+ expr_type ,
914
+ NULL ));
915
+
916
+ /* Ensure that value belongs to the range */
917
+ if (cmp_bounds (& cmp_finfo , collid , & fake_value_bound , & min ) < 0
918
+ || cmp_bounds (& cmp_finfo , collid , & fake_value_bound , & max ) >= 0 )
868
919
{
869
920
elog (ERROR ,
870
921
"specified value does not fit into the range [%s, %s)" ,
@@ -884,16 +935,6 @@ split_range_partitions(PG_FUNCTION_ARGS)
884
935
new_partition_ts ,
885
936
ri_constr , ri_relids );
886
937
887
- /* get_pathman_relation_info() will refresh this entry */
888
- invalidate_pathman_relation_info (parent , NULL );
889
-
890
- prel = get_pathman_relation_info (parent );
891
- shout_if_prel_is_invalid (parent , prel , PT_RANGE );
892
-
893
- // attname = get_attname(prel->key, prel->attnum);
894
- // attnum = get_attnum(partition, attname);
895
-
896
- /* Copy data */
897
938
bound = build_range_condition_internal (partition ,
898
939
expr_cstr ,
899
940
& fake_value_bound ,
@@ -906,30 +947,29 @@ split_range_partitions(PG_FUNCTION_ARGS)
906
947
/* Prevent RI triggers from complaining during data migration */
907
948
disable_ri_triggers ();
908
949
950
+ /* Migrate data */
909
951
query = psprintf ("WITH part_data AS ( "
910
952
" DELETE FROM %s WHERE %s RETURNING *) "
911
953
"INSERT INTO %s SELECT * FROM part_data" ,
912
954
get_qualified_rel_name (partition ),
913
955
bound ,
914
956
get_qualified_rel_name (new_partition ));
915
957
SPI_exec (query , 0 );
916
-
917
958
enable_ri_triggers ();
959
+ SPI_finish ();
918
960
919
- /* Alter constraint */
961
+ /* Alter constraint for the original partition */
920
962
modify_range_constraint (partition ,
921
963
expr_cstr ,
922
964
expr_type ,
923
965
& min ,
924
966
& fake_value_bound );
925
967
926
- SPI_finish ();
927
968
928
969
/* get_pathman_relation_info() will refresh this entry */
929
970
invalidate_pathman_relation_info (parent , NULL );
930
971
931
- // PG_RETURN_VOID();
932
- PG_RETURN_OID (new_partition );
972
+ return new_partition ;
933
973
}
934
974
935
975
/*
0 commit comments