@@ -41,6 +41,10 @@ static Datum extract_binary_interval_from_text(Datum interval_text,
4141Oid part_atttype ,
4242Oid * interval_type );
4343
44+ static void extract_op_func_and_ret_type (char * opname ,Oid type1 ,Oid type2 ,
45+ Oid * move_bound_op_func ,
46+ Oid * move_bound_op_ret_type );
47+
4448static Oid spawn_partitions_val (Oid parent_relid ,
4549Datum range_bound_min ,
4650Datum range_bound_max ,
@@ -353,6 +357,29 @@ extract_binary_interval_from_text(Datum interval_text,/* interval as TEXT */
353357return interval_binary ;
354358}
355359
360+ /*
361+ * Fetch binary operator by name and return it's function and ret type.
362+ */
363+ static void
364+ extract_op_func_and_ret_type (char * opname ,Oid type1 ,Oid type2 ,
365+ Oid * move_bound_op_func ,/* returned value #1 */
366+ Oid * move_bound_op_ret_type )/* returned value #2 */
367+ {
368+ Operator op ;
369+
370+ /* Get "move bound operator" descriptor */
371+ op = get_binary_operator (opname ,type1 ,type2 );
372+ if (!op )
373+ elog (ERROR ,"missing %s operator for types %s and %s" ,
374+ opname ,format_type_be (type1 ),format_type_be (type2 ));
375+
376+ * move_bound_op_func = oprfuncid (op );
377+ * move_bound_op_ret_type = get_operator_ret_type (op );
378+
379+ /* Don't forget to release system cache */
380+ ReleaseSysCache (op );
381+ }
382+
356383/*
357384 * Append\prepend partitions if there's no partition to store 'value'.
358385 *
@@ -373,8 +400,8 @@ spawn_partitions_val(Oid parent_relid,/* parent's Oid */
373400{
374401bool should_append ;/* append or prepend? */
375402
376- Operator move_bound_op ; /*descriptor */
377- Oid move_bound_optype ; /* operator's ret type */
403+ Oid move_bound_op_func , /*operator's function */
404+ move_bound_op_ret_type ; /* operator's ret type */
378405
379406FmgrInfo cmp_value_bound_finfo ,/* exec 'value (>=|<) bound' */
380407move_bound_finfo ;/* exec 'bound + interval' */
@@ -404,36 +431,45 @@ spawn_partitions_val(Oid parent_relid,/* parent's Oid */
404431/* There's a gap, halt and emit ERROR */
405432else elog (ERROR ,"cannot spawn a partition inside a gap" );
406433
407- /* Get "move bound operator" descriptor */
408- move_bound_op = get_binary_operator (should_append ?"+" :"-" ,
409- range_bound_type ,
410- interval_type );
411- /* Get operator's ret type */
412- move_bound_optype = get_operator_ret_type (move_bound_op );
413-
414- /* Get operator's underlying function */
415- fmgr_info (oprfuncid (move_bound_op ),& move_bound_finfo );
416-
417- /* Don't forget to release system cache */
418- ReleaseSysCache (move_bound_op );
434+ /* Fetch operator's underlying function and ret type */
435+ extract_op_func_and_ret_type (should_append ?"+" :"-" ,
436+ range_bound_type ,
437+ interval_type ,
438+ & move_bound_op_func ,
439+ & move_bound_op_ret_type );
419440
420- /* Performsome casts if types don't match */
421- if (move_bound_optype != range_bound_type )
441+ /* Perform casts if types don't match (e.g. date + interval = timestamp) */
442+ if (move_bound_op_ret_type != range_bound_type )
422443{
444+ /* Cast 'cur_leading_bound' to 'move_bound_op_ret_type' */
423445cur_leading_bound = perform_type_cast (cur_leading_bound ,
424446range_bound_type ,
425- move_bound_optype ,
447+ move_bound_op_ret_type ,
426448NULL );/* might emit ERROR */
427449
428450/* Update 'range_bound_type' */
429- range_bound_type = move_bound_optype ;
451+ range_bound_type = move_bound_op_ret_type ;
430452
431453/* Fetch new comparison function */
432454fill_type_cmp_fmgr_info (& cmp_value_bound_finfo ,
433455value_type ,
434456range_bound_type );
457+
458+ /* Since type has changed, fetch another operator */
459+ extract_op_func_and_ret_type (should_append ?"+" :"-" ,
460+ range_bound_type ,
461+ interval_type ,
462+ & move_bound_op_func ,
463+ & move_bound_op_ret_type );
464+
465+ /* What, again? Don't want to deal with this nightmare */
466+ if (move_bound_op_ret_type != range_bound_type )
467+ elog (ERROR ,"error in spawn_partitions_val()" );
435468}
436469
470+ /* Get operator's underlying function */
471+ fmgr_info (move_bound_op_func ,& move_bound_finfo );
472+
437473/* Execute comparison function cmp(value, cur_leading_bound) */
438474while (should_append ?
439475check_ge (& cmp_value_bound_finfo ,value ,cur_leading_bound ) :