@@ -72,6 +72,10 @@ static void modify_range_constraint(Oid partition_relid,
7272const Bound * upper );
7373static char * get_qualified_rel_name (Oid relid );
7474static 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 );
7579static bool interval_is_trivial (Oid atttype ,
7680Datum interval ,
7781Oid interval_type );
@@ -787,34 +791,36 @@ merge_range_partitions_internal(Oid parent, Oid *parts, uint32 nparts)
787791Datum
788792split_range_partitions (PG_FUNCTION_ARGS )
789793{
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 ;
794799
795800/* Optional: name & tablespace */
796801RangeVar * new_partition_rv = NULL ;
797- char * new_partition_ts = NULL ;
802+ char * new_partition_ts ;
798803
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 ;
813804PartParentSearch parent_search ;
814805
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" )));
817822
823+ /* New partition's name (optional) */
818824if (!PG_ARGISNULL (2 ))
819825{
820826List * qualified_name ;
@@ -825,14 +831,54 @@ split_range_partitions(PG_FUNCTION_ARGS)
825831new_partition_rv = makeRangeVarFromNameList (qualified_name );
826832}
827833
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 ;
830838
831839/* Get parent's relid */
832- parent = get_parent_of_partition (partition ,& parent_search );
840+ parent_relid = get_parent_of_partition (partition_relid ,& parent_search );
833841if (parent_search != PPS_ENTRY_PART_PARENT )
834842elog (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 ;
836882
837883/* Lock parent and partition */
838884prevent_relation_modification_internal (partition );
@@ -846,6 +892,7 @@ split_range_partitions(PG_FUNCTION_ARGS)
846892ranges = PrelGetRangesArray (prel );
847893expr_cstr = pstrdup (prel -> expr_cstr );
848894expr_type = prel -> ev_type ;
895+ collid = prel -> ev_collid ;
849896
850897/* Look for the specified partition's range */
851898for (i = 0 ;i < PrelChildrenCount (prel );i ++ )
@@ -860,11 +907,15 @@ split_range_partitions(PG_FUNCTION_ARGS)
860907min = CopyBound (& rentry -> min ,prel -> ev_byval ,prel -> ev_len );
861908max = CopyBound (& rentry -> max ,prel -> ev_byval ,prel -> ev_len );
862909
863- /* Ensure that value belongs to the range */
864910fill_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 )
868919{
869920elog (ERROR ,
870921"specified value does not fit into the range [%s, %s)" ,
@@ -884,16 +935,6 @@ split_range_partitions(PG_FUNCTION_ARGS)
884935new_partition_ts ,
885936ri_constr ,ri_relids );
886937
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 */
897938bound = build_range_condition_internal (partition ,
898939expr_cstr ,
899940& fake_value_bound ,
@@ -906,30 +947,29 @@ split_range_partitions(PG_FUNCTION_ARGS)
906947/* Prevent RI triggers from complaining during data migration */
907948disable_ri_triggers ();
908949
950+ /* Migrate data */
909951query = psprintf ("WITH part_data AS ( "
910952"DELETE FROM %s WHERE %s RETURNING *) "
911953"INSERT INTO %s SELECT * FROM part_data" ,
912954get_qualified_rel_name (partition ),
913955bound ,
914956get_qualified_rel_name (new_partition ));
915957SPI_exec (query ,0 );
916-
917958enable_ri_triggers ();
959+ SPI_finish ();
918960
919- /* Alter constraint */
961+ /* Alter constraintfor the original partition */
920962modify_range_constraint (partition ,
921963expr_cstr ,
922964expr_type ,
923965& min ,
924966& fake_value_bound );
925967
926- SPI_finish ();
927968
928969/* get_pathman_relation_info() will refresh this entry */
929970invalidate_pathman_relation_info (parent ,NULL );
930971
931- // PG_RETURN_VOID();
932- PG_RETURN_OID (new_partition );
972+ return new_partition ;
933973}
934974
935975/*