From a92b9a7cf58c20da4d56a84d961fb8d6e3af53ce Mon Sep 17 00:00:00 2001
From: Alexandre Felipe <o.alexandre.felipe@gmail.com>
Date: Fri, 3 Apr 2026 07:35:00 +0100
Subject: [PATCH 4/4] SLOPE: catalog changes

Add prosupport annotations to built-in monotonic functions,
enabling the SLOPE optimization to use indexes for ORDER BY f(x).

Functions annotated with some monotonicity
- Arithmetic: int2/4/8 and float4/8 add, subtract, multiply, divide
- Unary minus: int2um, int4um, int8um, float4um, float8um
- Rounding: floor, ceil (float8 and numeric variants)
- Date/time: date_trunc (timestamp, timestamptz, interval)
- Conversion from time samp types to date.

Also adds the prosupport function entries to pg_proc.dat
- arg0_asc_slope_support (OID 9954)
- arg0_desc_slope_support (OID 9955)
- arg1_asc_slope_support (OID 9956)
- diff_slope_support (OID 9957)
- addition_slope_support (OID 9958)
- multiply_slope_support (OID 9959)
- divide_slope_support (OID 9960)

Bump catversion for catalog changes.
---
 src/include/catalog/catversion.h |   2 +-
 src/include/catalog/pg_proc.dat  | 192 ++++++++++++++++++-------------
 2 files changed, 113 insertions(+), 81 deletions(-)

diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 81b2bf39b3f..339117869c5 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	202603301
+#define CATALOG_VERSION_NO	202604011
 
 #endif
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3579cec5744..2a9c632a1be 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -420,8 +420,8 @@
   proargtypes => 'internal oid internal int2 internal',
   prosrc => 'areajoinsel' },
 { oid => '141',
-  proname => 'int4mul', prorettype => 'int4', proargtypes => 'int4 int4',
-  prosrc => 'int4mul' },
+  proname => 'int4mul', prosupport => 'multiply_slope_support',
+  prorettype => 'int4', proargtypes => 'int4 int4', prosrc => 'int4mul' },
 { oid => '144',
   proname => 'int4ne', proleakproof => 't', prorettype => 'bool',
   proargtypes => 'int4 int4', prosrc => 'int4ne' },
@@ -447,14 +447,14 @@
   proname => 'int2ge', proleakproof => 't', prorettype => 'bool',
   proargtypes => 'int2 int2', prosrc => 'int2ge' },
 { oid => '152',
-  proname => 'int2mul', prorettype => 'int2', proargtypes => 'int2 int2',
-  prosrc => 'int2mul' },
+  proname => 'int2mul', prosupport => 'multiply_slope_support',
+  prorettype => 'int2', proargtypes => 'int2 int2', prosrc => 'int2mul' },
 { oid => '153',
-  proname => 'int2div', prorettype => 'int2', proargtypes => 'int2 int2',
-  prosrc => 'int2div' },
+  proname => 'int2div', prosupport => 'divide_slope_support',
+  prorettype => 'int2', proargtypes => 'int2 int2', prosrc => 'int2div' },
 { oid => '154',
-  proname => 'int4div', prorettype => 'int4', proargtypes => 'int4 int4',
-  prosrc => 'int4div' },
+  proname => 'int4div', prosupport => 'divide_slope_support',
+  prorettype => 'int4', proargtypes => 'int4 int4', prosrc => 'int4div' },
 { oid => '155',
   proname => 'int2mod', prorettype => 'int2', proargtypes => 'int2 int2',
   prosrc => 'int2mod' },
@@ -513,29 +513,29 @@
   proname => 'int42div', prorettype => 'int4', proargtypes => 'int4 int2',
   prosrc => 'int42div' },
 { oid => '176',
-  proname => 'int2pl', prorettype => 'int2', proargtypes => 'int2 int2',
-  prosrc => 'int2pl' },
+  proname => 'int2pl', prosupport => 'addition_slope_support',
+  prorettype => 'int2', proargtypes => 'int2 int2', prosrc => 'int2pl' },
 { oid => '177',
-  proname => 'int4pl', prorettype => 'int4', proargtypes => 'int4 int4',
-  prosrc => 'int4pl' },
+  proname => 'int4pl', prosupport => 'addition_slope_support',
+  prorettype => 'int4', proargtypes => 'int4 int4', prosrc => 'int4pl' },
 { oid => '178',
-  proname => 'int24pl', prorettype => 'int4', proargtypes => 'int2 int4',
-  prosrc => 'int24pl' },
+  proname => 'int24pl', prosupport => 'addition_slope_support',
+  prorettype => 'int4', proargtypes => 'int2 int4', prosrc => 'int24pl' },
 { oid => '179',
-  proname => 'int42pl', prorettype => 'int4', proargtypes => 'int4 int2',
-  prosrc => 'int42pl' },
+  proname => 'int42pl', prosupport => 'addition_slope_support',
+  prorettype => 'int4', proargtypes => 'int4 int2', prosrc => 'int42pl' },
 { oid => '180',
-  proname => 'int2mi', prorettype => 'int2', proargtypes => 'int2 int2',
-  prosrc => 'int2mi' },
+  proname => 'int2mi', prosupport => 'diff_slope_support',
+  prorettype => 'int2', proargtypes => 'int2 int2', prosrc => 'int2mi' },
 { oid => '181',
-  proname => 'int4mi', prorettype => 'int4', proargtypes => 'int4 int4',
-  prosrc => 'int4mi' },
+  proname => 'int4mi', prosupport => 'diff_slope_support',
+  prorettype => 'int4', proargtypes => 'int4 int4', prosrc => 'int4mi' },
 { oid => '182',
-  proname => 'int24mi', prorettype => 'int4', proargtypes => 'int2 int4',
-  prosrc => 'int24mi' },
+  proname => 'int24mi', prosupport => 'diff_slope_support',
+  prorettype => 'int4', proargtypes => 'int2 int4', prosrc => 'int24mi' },
 { oid => '183',
-  proname => 'int42mi', prorettype => 'int4', proargtypes => 'int4 int2',
-  prosrc => 'int42mi' },
+  proname => 'int42mi', prosupport => 'diff_slope_support',
+  prorettype => 'int4', proargtypes => 'int4 int2', prosrc => 'int42mi' },
 { oid => '184',
   proname => 'oideq', proleakproof => 't', prorettype => 'bool',
   proargtypes => 'oid oid', prosrc => 'oideq' },
@@ -590,20 +590,20 @@
   proname => 'float4out', prorettype => 'cstring', proargtypes => 'float4',
   prosrc => 'float4out' },
 { oid => '202',
-  proname => 'float4mul', prorettype => 'float4',
-  proargtypes => 'float4 float4', prosrc => 'float4mul' },
+  proname => 'float4mul', prosupport => 'multiply_slope_support',
+  prorettype => 'float4', proargtypes => 'float4 float4', prosrc => 'float4mul' },
 { oid => '203',
-  proname => 'float4div', prorettype => 'float4',
-  proargtypes => 'float4 float4', prosrc => 'float4div' },
+  proname => 'float4div', prosupport => 'divide_slope_support',
+  prorettype => 'float4', proargtypes => 'float4 float4', prosrc => 'float4div' },
 { oid => '204',
-  proname => 'float4pl', prorettype => 'float4', proargtypes => 'float4 float4',
-  prosrc => 'float4pl' },
+  proname => 'float4pl', prosupport => 'addition_slope_support',
+  prorettype => 'float4', proargtypes => 'float4 float4', prosrc => 'float4pl' },
 { oid => '205',
-  proname => 'float4mi', prorettype => 'float4', proargtypes => 'float4 float4',
-  prosrc => 'float4mi' },
+  proname => 'float4mi', prosupport => 'diff_slope_support',
+  prorettype => 'float4', proargtypes => 'float4 float4', prosrc => 'float4mi' },
 { oid => '206',
-  proname => 'float4um', prorettype => 'float4', proargtypes => 'float4',
-  prosrc => 'float4um' },
+  proname => 'float4um', prosupport => 'arg0_desc_slope_support',
+  prorettype => 'float4', proargtypes => 'float4', prosrc => 'float4um' },
 { oid => '207',
   proname => 'float4abs', prorettype => 'float4', proargtypes => 'float4',
   prosrc => 'float4abs' },
@@ -618,11 +618,11 @@
   proargtypes => 'float4 float4', prosrc => 'float4smaller' },
 
 { oid => '212',
-  proname => 'int4um', prorettype => 'int4', proargtypes => 'int4',
-  prosrc => 'int4um' },
+  proname => 'int4um', prosupport => 'arg0_desc_slope_support',
+  prorettype => 'int4', proargtypes => 'int4', prosrc => 'int4um' },
 { oid => '213',
-  proname => 'int2um', prorettype => 'int2', proargtypes => 'int2',
-  prosrc => 'int2um' },
+  proname => 'int2um', prosupport => 'arg0_desc_slope_support',
+  prorettype => 'int2', proargtypes => 'int2', prosrc => 'int2um' },
 
 { oid => '214', descr => 'I/O',
   proname => 'float8in', prorettype => 'float8', proargtypes => 'cstring',
@@ -631,20 +631,20 @@
   proname => 'float8out', prorettype => 'cstring', proargtypes => 'float8',
   prosrc => 'float8out' },
 { oid => '216',
-  proname => 'float8mul', prorettype => 'float8',
-  proargtypes => 'float8 float8', prosrc => 'float8mul' },
+  proname => 'float8mul', prosupport => 'multiply_slope_support',
+  prorettype => 'float8', proargtypes => 'float8 float8', prosrc => 'float8mul' },
 { oid => '217',
-  proname => 'float8div', prorettype => 'float8',
-  proargtypes => 'float8 float8', prosrc => 'float8div' },
+  proname => 'float8div', prosupport => 'divide_slope_support',
+  prorettype => 'float8', proargtypes => 'float8 float8', prosrc => 'float8div' },
 { oid => '218',
-  proname => 'float8pl', prorettype => 'float8', proargtypes => 'float8 float8',
-  prosrc => 'float8pl' },
+  proname => 'float8pl', prosupport => 'addition_slope_support',
+  prorettype => 'float8', proargtypes => 'float8 float8', prosrc => 'float8pl' },
 { oid => '219',
-  proname => 'float8mi', prorettype => 'float8', proargtypes => 'float8 float8',
-  prosrc => 'float8mi' },
+  proname => 'float8mi', prosupport => 'diff_slope_support',
+  prorettype => 'float8', proargtypes => 'float8 float8', prosrc => 'float8mi' },
 { oid => '220',
-  proname => 'float8um', prorettype => 'float8', proargtypes => 'float8',
-  prosrc => 'float8um' },
+  proname => 'float8um', prosupport => 'arg0_desc_slope_support',
+  prorettype => 'float8', proargtypes => 'float8', prosrc => 'float8um' },
 { oid => '221',
   proname => 'float8abs', prorettype => 'float8', proargtypes => 'float8',
   prosrc => 'float8abs' },
@@ -675,14 +675,14 @@
   proname => 'dtrunc', prorettype => 'float8', proargtypes => 'float8',
   prosrc => 'dtrunc' },
 { oid => '2308', descr => 'nearest integer >= value',
-  proname => 'ceil', prorettype => 'float8', proargtypes => 'float8',
-  prosrc => 'dceil' },
+  proname => 'ceil', prosupport => 'arg0_asc_slope_support',
+  prorettype => 'float8', proargtypes => 'float8', prosrc => 'dceil' },
 { oid => '2320', descr => 'nearest integer >= value',
   proname => 'ceiling', prorettype => 'float8', proargtypes => 'float8',
   prosrc => 'dceil' },
 { oid => '2309', descr => 'nearest integer <= value',
-  proname => 'floor', prorettype => 'float8', proargtypes => 'float8',
-  prosrc => 'dfloor' },
+  proname => 'floor', prosupport => 'arg0_asc_slope_support',
+  prorettype => 'float8', proargtypes => 'float8', prosrc => 'dfloor' },
 { oid => '2310', descr => 'sign of value',
   proname => 'sign', prorettype => 'float8', proargtypes => 'float8',
   prosrc => 'dsign' },
@@ -1378,20 +1378,20 @@
   proname => 'int8out', prorettype => 'cstring', proargtypes => 'int8',
   prosrc => 'int8out' },
 { oid => '462',
-  proname => 'int8um', prorettype => 'int8', proargtypes => 'int8',
-  prosrc => 'int8um' },
+  proname => 'int8um', prosupport => 'arg0_desc_slope_support',
+  prorettype => 'int8', proargtypes => 'int8', prosrc => 'int8um' },
 { oid => '463',
-  proname => 'int8pl', prorettype => 'int8', proargtypes => 'int8 int8',
-  prosrc => 'int8pl' },
+  proname => 'int8pl', prosupport => 'addition_slope_support',
+  prorettype => 'int8', proargtypes => 'int8 int8', prosrc => 'int8pl' },
 { oid => '464',
-  proname => 'int8mi', prorettype => 'int8', proargtypes => 'int8 int8',
-  prosrc => 'int8mi' },
+  proname => 'int8mi', prosupport => 'diff_slope_support',
+  prorettype => 'int8', proargtypes => 'int8 int8', prosrc => 'int8mi' },
 { oid => '465',
-  proname => 'int8mul', prorettype => 'int8', proargtypes => 'int8 int8',
-  prosrc => 'int8mul' },
+  proname => 'int8mul', prosupport => 'multiply_slope_support',
+  prorettype => 'int8', proargtypes => 'int8 int8', prosrc => 'int8mul' },
 { oid => '466',
-  proname => 'int8div', prorettype => 'int8', proargtypes => 'int8 int8',
-  prosrc => 'int8div' },
+  proname => 'int8div', prosupport => 'divide_slope_support',
+  prorettype => 'int8', proargtypes => 'int8 int8', prosrc => 'int8div' },
 { oid => '467',
   proname => 'int8eq', proleakproof => 't', prorettype => 'bool',
   proargtypes => 'int8 int8', prosrc => 'int8eq' },
@@ -2498,7 +2498,8 @@
   proname => 'extract', prorettype => 'numeric', proargtypes => 'text interval',
   prosrc => 'extract_interval' },
 { oid => '1174', descr => 'convert date to timestamp with time zone',
-  proname => 'timestamptz', provolatile => 's', prorettype => 'timestamptz',
+  proname => 'timestamptz', prosupport => 'arg0_asc_slope_support',
+  provolatile => 's', prorettype => 'timestamptz',
   proargtypes => 'date', prosrc => 'date_timestamptz' },
 { oid => '2711',
   descr => 'promote groups of 24 hours to numbers of days and promote groups of 30 days to numbers of months',
@@ -2515,7 +2516,8 @@
   prorettype => 'timestamptz', proargtypes => 'date time',
   prosrc => 'see system_functions.sql' },
 { oid => '1178', descr => 'convert timestamp with time zone to date',
-  proname => 'date', provolatile => 's', prorettype => 'date',
+  proname => 'date', prosupport => 'arg0_asc_slope_support',
+  provolatile => 's', prorettype => 'date',
   proargtypes => 'timestamptz', prosrc => 'timestamptz_date' },
 { oid => '1181',
   descr => 'age of a transaction ID, in transactions before current transaction',
@@ -2595,15 +2597,16 @@
 
 { oid => '1217',
   descr => 'truncate timestamp with time zone to specified units',
-  proname => 'date_trunc', provolatile => 's', prorettype => 'timestamptz',
+  proname => 'date_trunc', prosupport => 'arg1_asc_slope_support',
+  provolatile => 's', prorettype => 'timestamptz',
   proargtypes => 'text timestamptz', prosrc => 'timestamptz_trunc' },
 { oid => '1284',
   descr => 'truncate timestamp with time zone to specified units in specified time zone',
   proname => 'date_trunc', prorettype => 'timestamptz',
   proargtypes => 'text timestamptz text', prosrc => 'timestamptz_trunc_zone' },
 { oid => '1218', descr => 'truncate interval to specified units',
-  proname => 'date_trunc', prorettype => 'interval',
-  proargtypes => 'text interval', prosrc => 'interval_trunc' },
+  proname => 'date_trunc', prosupport => 'arg1_asc_slope_support',
+  prorettype => 'interval', proargtypes => 'text interval', prosrc => 'interval_trunc' },
 
 { oid => '1219', descr => 'increment',
   proname => 'int8inc', prorettype => 'int8', proargtypes => 'int8',
@@ -2655,8 +2658,9 @@
   proname => 'overlaps', proisstrict => 'f', prorettype => 'bool',
   proargtypes => 'timetz timetz timetz timetz', prosrc => 'overlaps_timetz' },
 { oid => '1272',
-  proname => 'datetime_pl', prorettype => 'timestamp',
-  proargtypes => 'date time', prosrc => 'datetime_timestamp' },
+  proname => 'datetime_pl', prosupport => 'addition_slope_support',
+  prorettype => 'timestamp', proargtypes => 'date time',
+  prosrc => 'datetime_timestamp' },
 { oid => '1273', descr => 'extract field from time with time zone',
   proname => 'date_part', prorettype => 'float8', proargtypes => 'text timetz',
   prosrc => 'timetz_part' },
@@ -4616,14 +4620,14 @@
   proname => 'trunc', prolang => 'sql', prorettype => 'numeric',
   proargtypes => 'numeric', prosrc => 'see system_functions.sql' },
 { oid => '1711', descr => 'nearest integer >= value',
-  proname => 'ceil', prorettype => 'numeric', proargtypes => 'numeric',
-  prosrc => 'numeric_ceil' },
+  proname => 'ceil', prosupport => 'arg0_asc_slope_support',
+  prorettype => 'numeric', proargtypes => 'numeric', prosrc => 'numeric_ceil' },
 { oid => '2167', descr => 'nearest integer >= value',
   proname => 'ceiling', prorettype => 'numeric', proargtypes => 'numeric',
   prosrc => 'numeric_ceil' },
 { oid => '1712', descr => 'nearest integer <= value',
-  proname => 'floor', prorettype => 'numeric', proargtypes => 'numeric',
-  prosrc => 'numeric_floor' },
+  proname => 'floor', prosupport => 'arg0_asc_slope_support',
+  prorettype => 'numeric', proargtypes => 'numeric', prosrc => 'numeric_floor' },
 { oid => '1718',
   proname => 'numeric_eq', prorettype => 'bool',
   proargtypes => 'numeric numeric', prosrc => 'numeric_eq' },
@@ -6376,8 +6380,8 @@
   proname => 'time', provolatile => 's', prorettype => 'time',
   proargtypes => 'timestamptz', prosrc => 'timestamptz_time' },
 { oid => '2020', descr => 'truncate timestamp to specified units',
-  proname => 'date_trunc', prorettype => 'timestamp',
-  proargtypes => 'text timestamp', prosrc => 'timestamp_trunc' },
+  proname => 'date_trunc', prosupport => 'arg1_asc_slope_support',
+  prorettype => 'timestamp', proargtypes => 'text timestamp', prosrc => 'timestamp_trunc' },
 
 { oid => '6177', descr => 'bin timestamp into specified interval',
   proname => 'date_bin', prorettype => 'timestamp',
@@ -6395,19 +6399,24 @@
   proname => 'extract', prorettype => 'numeric',
   proargtypes => 'text timestamp', prosrc => 'extract_timestamp' },
 { oid => '2024', descr => 'convert date to timestamp',
-  proname => 'timestamp', prorettype => 'timestamp', proargtypes => 'date',
+  proname => 'timestamp', prosupport => 'arg0_asc_slope_support',
+  prorettype => 'timestamp', proargtypes => 'date',
   prosrc => 'date_timestamp' },
 { oid => '2025', descr => 'convert date and time to timestamp',
-  proname => 'timestamp', prorettype => 'timestamp', proargtypes => 'date time',
+  proname => 'timestamp', prosupport => 'addition_slope_support',
+  prorettype => 'timestamp', proargtypes => 'date time',
   prosrc => 'datetime_timestamp' },
 { oid => '2027', descr => 'convert timestamp with time zone to timestamp',
-  proname => 'timestamp', provolatile => 's', prorettype => 'timestamp',
+  proname => 'timestamp', prosupport => 'arg0_asc_slope_support',
+  provolatile => 's', prorettype => 'timestamp',
   proargtypes => 'timestamptz', prosrc => 'timestamptz_timestamp' },
 { oid => '2028', descr => 'convert timestamp to timestamp with time zone',
-  proname => 'timestamptz', provolatile => 's', prorettype => 'timestamptz',
+  proname => 'timestamptz', prosupport => 'arg0_asc_slope_support',
+  provolatile => 's', prorettype => 'timestamptz',
   proargtypes => 'timestamp', prosrc => 'timestamp_timestamptz' },
 { oid => '2029', descr => 'convert timestamp to date',
-  proname => 'date', prorettype => 'date', proargtypes => 'timestamp',
+  proname => 'date', prosupport => 'arg0_asc_slope_support',
+  prorettype => 'date', proargtypes => 'timestamp',
   prosrc => 'timestamp_date' },
 { oid => '2031',
   proname => 'timestamp_mi', prorettype => 'interval',
@@ -12785,6 +12794,29 @@
   proargnames => '{schemaname,relname,statistics_schemaname,statistics_name,inherited}',
   prosrc => 'pg_clear_extended_stats' },
 
+# monotonic support functions for scalar function ordering optimization (SLOPE)
+{ oid => '9954', descr => 'planner support for ascending slope in arg 0',
+  proname => 'arg0_asc_slope_support', prorettype => 'internal',
+  proargtypes => 'internal', prosrc => 'arg0_asc_slope_support' },
+{ oid => '9955', descr => 'planner support for descending slope in arg 0',
+  proname => 'arg0_desc_slope_support', prorettype => 'internal',
+  proargtypes => 'internal', prosrc => 'arg0_desc_slope_support' },
+{ oid => '9956', descr => 'planner support for ascending slope in arg 1',
+  proname => 'arg1_asc_slope_support', prorettype => 'internal',
+  proargtypes => 'internal', prosrc => 'arg1_asc_slope_support' },
+{ oid => '9957', descr => 'planner support for diff slope (asc arg0, desc arg1)',
+  proname => 'diff_slope_support', prorettype => 'internal',
+  proargtypes => 'internal', prosrc => 'diff_slope_support' },
+{ oid => '9958', descr => 'planner support for addition slope (asc both args)',
+  proname => 'addition_slope_support', prorettype => 'internal',
+  proargtypes => 'internal', prosrc => 'addition_slope_support' },
+{ oid => '9959', descr => 'planner support for multiply slope (sign-dependent)',
+  proname => 'multiply_slope_support', prorettype => 'internal',
+  proargtypes => 'internal', prosrc => 'multiply_slope_support' },
+{ oid => '9960', descr => 'planner support for divide slope (sign-dependent)',
+  proname => 'divide_slope_support', prorettype => 'internal',
+  proargtypes => 'internal', prosrc => 'divide_slope_support' },
+
 # AIO related functions
 { oid => '6399', descr => 'information about in-progress asynchronous IOs',
   proname => 'pg_get_aios', prorows => '100', proretset => 't',
-- 
2.53.0

