@@ -41,6 +41,10 @@ static Datum extract_binary_interval_from_text(Datum interval_text,
41
41
Oid part_atttype ,
42
42
Oid * interval_type );
43
43
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
+
44
48
static Oid spawn_partitions_val (Oid parent_relid ,
45
49
Datum range_bound_min ,
46
50
Datum range_bound_max ,
@@ -353,6 +357,29 @@ extract_binary_interval_from_text(Datum interval_text, /* interval as TEXT */
353
357
return interval_binary ;
354
358
}
355
359
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
+
356
383
/*
357
384
* Append\prepend partitions if there's no partition to store 'value'.
358
385
*
@@ -373,8 +400,8 @@ spawn_partitions_val(Oid parent_relid, /* parent's Oid */
373
400
{
374
401
bool should_append ; /* append or prepend? */
375
402
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 */
378
405
379
406
FmgrInfo cmp_value_bound_finfo , /* exec 'value (>=|<) bound' */
380
407
move_bound_finfo ; /* exec 'bound + interval' */
@@ -404,36 +431,45 @@ spawn_partitions_val(Oid parent_relid, /* parent's Oid */
404
431
/* There's a gap, halt and emit ERROR */
405
432
else elog (ERROR , "cannot spawn a partition inside a gap" );
406
433
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 );
419
440
420
- /* Perform some 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 )
422
443
{
444
+ /* Cast 'cur_leading_bound' to 'move_bound_op_ret_type' */
423
445
cur_leading_bound = perform_type_cast (cur_leading_bound ,
424
446
range_bound_type ,
425
- move_bound_optype ,
447
+ move_bound_op_ret_type ,
426
448
NULL ); /* might emit ERROR */
427
449
428
450
/* Update 'range_bound_type' */
429
- range_bound_type = move_bound_optype ;
451
+ range_bound_type = move_bound_op_ret_type ;
430
452
431
453
/* Fetch new comparison function */
432
454
fill_type_cmp_fmgr_info (& cmp_value_bound_finfo ,
433
455
value_type ,
434
456
range_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()" );
435
468
}
436
469
470
+ /* Get operator's underlying function */
471
+ fmgr_info (move_bound_op_func , & move_bound_finfo );
472
+
437
473
/* Execute comparison function cmp(value, cur_leading_bound) */
438
474
while (should_append ?
439
475
check_ge (& cmp_value_bound_finfo , value , cur_leading_bound ) :
0 commit comments