From 70976c7549ab7374ee2158d23722adb3313506db Mon Sep 17 00:00:00 2001
From: yangyuanzhuo <1197620467@qq.com>
Date: Thu, 26 Feb 2026 13:29:38 +0800
Subject: [PATCH v1 2/2] Addition and subtraction operations for the interval
 and integer types

When working on Oracle compatibility-related tasks, I discovered that
PostgreSQL does not support the addition and subtraction operations
between interval and integer (such usage is usually seen when performing
time calculations in Oracle). Therefore, I implemented it.

Author:Yuanzhuo Yang <1197620467@qq.com>
---
 src/backend/utils/adt/timestamp.c   | 107 ++++++++++++++++++++++++++++++++++++
 src/include/catalog/pg_operator.dat |  22 ++++++++
 src/include/catalog/pg_proc.dat     |  24 ++++++++
 3 files changed, 153 insertions(+)

diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index e260318..c348de9 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -3217,6 +3217,113 @@ timestamp_mi_interval(PG_FUNCTION_ARGS)
 							   PointerGetDatum(&tspan));
 }
 
+/*
+ * interval + integer
+ */
+Datum
+interval_plus_int4(PG_FUNCTION_ARGS)
+{
+    Interval   *interval = PG_GETARG_INTERVAL_P(0);
+    int32       days = PG_GETARG_INT32(1);
+    Interval   *result;
+    
+    Interval    days_interval;
+    
+    result = (Interval *) palloc(sizeof(Interval));
+    
+    days_interval.month = 0;
+    days_interval.day = days;
+    days_interval.time = 0;
+    
+    result = DatumGetIntervalP(DirectFunctionCall2(
+        interval_pl,
+        IntervalPGetDatum(interval),
+        IntervalPGetDatum(&days_interval)
+    ));
+    
+    PG_RETURN_INTERVAL_P(result);
+}
+
+/*
+ * integer + interval
+ */
+Datum
+int4_plus_interval(PG_FUNCTION_ARGS)
+{
+    int32       days = PG_GETARG_INT32(0);
+    Interval   *interval = PG_GETARG_INTERVAL_P(1);
+    Interval   *result;
+    Interval    days_interval;
+    
+    days_interval.month = 0;
+    days_interval.day = days;
+    days_interval.time = 0;
+    
+    result = DatumGetIntervalP(DirectFunctionCall2(
+        interval_pl,
+        IntervalPGetDatum(interval),
+        IntervalPGetDatum(&days_interval)
+    ));
+    
+    PG_RETURN_INTERVAL_P(result);
+}
+/*
+ * interval - integer
+ */
+Datum
+interval_minus_int4(PG_FUNCTION_ARGS)
+{
+    Interval   *interval = PG_GETARG_INTERVAL_P(0);
+    int32       days = PG_GETARG_INT32(1);
+    Interval   *result;
+    Interval    days_interval;
+    
+    result = (Interval *) palloc(sizeof(Interval));
+    
+    days_interval.month = 0;
+    days_interval.day = -days;
+    days_interval.time = 0;
+    
+    /* interval + (-days) = interval - days */
+    result = DatumGetIntervalP(DirectFunctionCall2(
+        interval_pl,
+        IntervalPGetDatum(interval),
+        IntervalPGetDatum(&days_interval)
+    ));
+    
+    PG_RETURN_INTERVAL_P(result);
+}
+
+/*
+ * integer - interval
+ */
+Datum
+int4_minus_interval(PG_FUNCTION_ARGS)
+{
+    int32       days = PG_GETARG_INT32(0);
+    Interval   *interval = PG_GETARG_INTERVAL_P(1);
+    Interval   *result;
+    Interval    base_interval;
+    Interval    neg_interval;
+    
+    result = (Interval *) palloc(sizeof(Interval));
+
+    base_interval.month = 0;
+    base_interval.day = days;
+    base_interval.time = 0;
+
+    neg_interval.month = -interval->month;
+    neg_interval.day = -interval->day;
+    neg_interval.time = -interval->time;
+
+    result = DatumGetIntervalP(DirectFunctionCall2(
+        interval_pl,
+        IntervalPGetDatum(&base_interval),
+        IntervalPGetDatum(&neg_interval)
+    ));
+    
+    PG_RETURN_INTERVAL_P(result);
+}
 
 /* timestamptz_pl_interval_internal()
  * Add an interval to a timestamptz, in the given (or session) timezone.
diff --git a/src/include/catalog/pg_operator.dat b/src/include/catalog/pg_operator.dat
index 1465f13..ab88a1d 100644
--- a/src/include/catalog/pg_operator.dat
+++ b/src/include/catalog/pg_operator.dat
@@ -3486,4 +3486,26 @@
   oprcom => '<=(oid8,oid8)', oprnegate => '<(oid8,oid8)', oprcode => 'oid8ge',
   oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
 
+/* interval + integer */
+{ oid => '5200', oid_symbol => 'OPERATOR_INTERVAL_PLUS_INT4',
+  oprname => '+', oprleft => 'interval', oprright => 'int4',
+  oprresult => 'interval', oprcode => 'interval_plus_int4' },
+
+/* integer + interval */
+{ oid => '5201', oid_symbol => 'OPERATOR_INT4_PLUS_INTERVAL',
+  oprname => '+', oprleft => 'int4', oprright => 'interval',
+  oprresult => 'interval', oprcode => 'int4_plus_interval' },
+
+/* interval - integer */
+{ oid => '5202', oid_symbol => 'OPERATOR_INTERVAL_MINUS_INT4',
+  oprname => '-', oprleft => 'interval', oprright => 'int4',
+  oprresult => 'interval', 
+  oprcode => 'interval_minus_int4' },
+
+/* integer - interval */
+{ oid => '5203', oid_symbol => 'OPERATOR_INT4_MINUS_INTERVAL',
+  oprname => '-', oprleft => 'int4', oprright => 'interval',
+  oprresult => 'interval',
+  oprcode => 'int4_minus_interval' },
+  
 ]
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index dac4099..69b5b14 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12758,5 +12758,29 @@
 { oid => '8281', descr => 'hash',
   proname => 'hashoid8extended', prorettype => 'int8',
   proargtypes => 'oid8 int8', prosrc => 'hashoid8extended' },
+  
+{ oid => '5300',
+  proname => 'interval_plus_int4',
+  prorettype => 'interval',
+  proargtypes => 'interval int4',
+  prosrc => 'interval_plus_int4' },
+
+{ oid => '5301',
+  proname => 'int4_plus_interval',
+  prorettype => 'interval',
+  proargtypes => 'int4 interval',
+  prosrc => 'int4_plus_interval' },
+
+{ oid => '5302',
+  proname => 'interval_minus_int4',
+  prorettype => 'interval',
+  proargtypes => 'interval int4',
+  prosrc => 'interval_minus_int4' },
+
+{ oid => '5303',
+  proname => 'int4_minus_interval',
+  prorettype => 'interval',
+  proargtypes => 'int4 interval',
+  prosrc => 'int4_minus_interval' },
 
 ]
-- 
1.8.3.1

