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