Обсуждение: Mark unconditionally-safe implicit coercions as leakproof

Поиск
Список
Период
Сортировка

Mark unconditionally-safe implicit coercions as leakproof

От
Tom Lane
Дата:
I went through the system's built-in implicit coercions to see
which ones are unconditionally successful.  These could all be
marked leakproof, as per attached patch.  This came up in the
context of the nearby discussion about CASE, but it seems like
an independent improvement.  If you have a function f(int8)
that is leakproof, you don't want it to effectively become
non-leakproof when you apply it to an int4 or int2 column.

One that I didn't mark leakproof is rtrim1(), which is the
infrastructure for char(n) to text coercion.  It looks like it
actually does qualify right now, but the code is long enough and
complex enough that I think such a marking would be a bit unsafe.

Any objections?

            regards, tom lane

diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4b5af32440..3fed5725cb 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -698,10 +698,10 @@
   proname => 'dlog1', prorettype => 'float8', proargtypes => 'float8',
   prosrc => 'dlog1' },
 { oid => '235', descr => 'convert int2 to float8',
-  proname => 'float8', prorettype => 'float8', proargtypes => 'int2',
+  proname => 'float8', proleakproof => 't', prorettype => 'float8', proargtypes => 'int2',
   prosrc => 'i2tod' },
 { oid => '236', descr => 'convert int2 to float4',
-  proname => 'float4', prorettype => 'float4', proargtypes => 'int2',
+  proname => 'float4', proleakproof => 't', prorettype => 'float4', proargtypes => 'int2',
   prosrc => 'i2tof' },
 { oid => '237', descr => 'convert float8 to int2',
   proname => 'int2', prorettype => 'int2', proargtypes => 'float8',
@@ -879,25 +879,25 @@
   proargtypes => 'float8 float8 float8 int4', prosrc => 'width_bucket_float8' },

 { oid => '311', descr => 'convert float4 to float8',
-  proname => 'float8', prorettype => 'float8', proargtypes => 'float4',
+  proname => 'float8', proleakproof => 't', prorettype => 'float8', proargtypes => 'float4',
   prosrc => 'ftod' },
 { oid => '312', descr => 'convert float8 to float4',
   proname => 'float4', prorettype => 'float4', proargtypes => 'float8',
   prosrc => 'dtof' },
 { oid => '313', descr => 'convert int2 to int4',
-  proname => 'int4', prorettype => 'int4', proargtypes => 'int2',
+  proname => 'int4', proleakproof => 't', prorettype => 'int4', proargtypes => 'int2',
   prosrc => 'i2toi4' },
 { oid => '314', descr => 'convert int4 to int2',
   proname => 'int2', prorettype => 'int2', proargtypes => 'int4',
   prosrc => 'i4toi2' },
 { oid => '316', descr => 'convert int4 to float8',
-  proname => 'float8', prorettype => 'float8', proargtypes => 'int4',
+  proname => 'float8', proleakproof => 't', prorettype => 'float8', proargtypes => 'int4',
   prosrc => 'i4tod' },
 { oid => '317', descr => 'convert float8 to int4',
   proname => 'int4', prorettype => 'int4', proargtypes => 'float8',
   prosrc => 'dtoi4' },
 { oid => '318', descr => 'convert int4 to float4',
-  proname => 'float4', prorettype => 'float4', proargtypes => 'int4',
+  proname => 'float4', proleakproof => 't', prorettype => 'float4', proargtypes => 'int4',
   prosrc => 'i4tof' },
 { oid => '319', descr => 'convert float4 to int4',
   proname => 'int4', prorettype => 'int4', proargtypes => 'float4',
@@ -1150,16 +1150,16 @@
   proname => 'text', prorettype => 'text', proargtypes => 'bpchar',
   prosrc => 'rtrim1' },
 { oid => '406', descr => 'convert name to text',
-  proname => 'text', prorettype => 'text', proargtypes => 'name',
+  proname => 'text', proleakproof => 't', prorettype => 'text', proargtypes => 'name',
   prosrc => 'name_text' },
 { oid => '407', descr => 'convert text to name',
-  proname => 'name', prorettype => 'name', proargtypes => 'text',
+  proname => 'name', proleakproof => 't', prorettype => 'name', proargtypes => 'text',
   prosrc => 'text_name' },
 { oid => '408', descr => 'convert name to char(n)',
   proname => 'bpchar', prorettype => 'bpchar', proargtypes => 'name',
   prosrc => 'name_bpchar' },
 { oid => '409', descr => 'convert char(n) to name',
-  proname => 'name', prorettype => 'name', proargtypes => 'bpchar',
+  proname => 'name', proleakproof => 't', prorettype => 'name', proargtypes => 'bpchar',
   prosrc => 'bpchar_name' },

 { oid => '449', descr => 'hash',
@@ -1338,10 +1338,10 @@
   proname => 'int4', prorettype => 'int4', proargtypes => 'int8',
   prosrc => 'int84' },
 { oid => '481', descr => 'convert int4 to int8',
-  proname => 'int8', prorettype => 'int8', proargtypes => 'int4',
+  proname => 'int8', proleakproof => 't', prorettype => 'int8', proargtypes => 'int4',
   prosrc => 'int48' },
 { oid => '482', descr => 'convert int8 to float8',
-  proname => 'float8', prorettype => 'float8', proargtypes => 'int8',
+  proname => 'float8', proleakproof => 't', prorettype => 'float8', proargtypes => 'int8',
   prosrc => 'i8tod' },
 { oid => '483', descr => 'convert float8 to int8',
   proname => 'int8', prorettype => 'int8', proargtypes => 'float8',
@@ -1359,7 +1359,7 @@
   proargtypes => 'anyarray int8', prosrc => 'hash_array_extended' },

 { oid => '652', descr => 'convert int8 to float4',
-  proname => 'float4', prorettype => 'float4', proargtypes => 'int8',
+  proname => 'float4', proleakproof => 't', prorettype => 'float4', proargtypes => 'int8',
   prosrc => 'i8tof' },
 { oid => '653', descr => 'convert float4 to int8',
   proname => 'int8', prorettype => 'int8', proargtypes => 'float4',
@@ -1369,7 +1369,7 @@
   proname => 'int2', prorettype => 'int2', proargtypes => 'int8',
   prosrc => 'int82' },
 { oid => '754', descr => 'convert int2 to int8',
-  proname => 'int8', prorettype => 'int8', proargtypes => 'int2',
+  proname => 'int8', proleakproof => 't', prorettype => 'int8', proargtypes => 'int2',
   prosrc => 'int28' },

 { oid => '655',
@@ -2782,7 +2782,7 @@
   prosrc => 'textlen' },

 { oid => '1370', descr => 'convert time to interval',
-  proname => 'interval', prorettype => 'interval', proargtypes => 'time',
+  proname => 'interval', proleakproof => 't', prorettype => 'interval', proargtypes => 'time',
   prosrc => 'time_interval' },
 { oid => '1372', descr => 'character length',
   proname => 'char_length', prorettype => 'int4', proargtypes => 'bpchar',
@@ -2861,10 +2861,10 @@
 # OIDS 1400 - 1499

 { oid => '1400', descr => 'convert varchar to name',
-  proname => 'name', prorettype => 'name', proargtypes => 'varchar',
+  proname => 'name', proleakproof => 't', prorettype => 'name', proargtypes => 'varchar',
   prosrc => 'text_name' },
 { oid => '1401', descr => 'convert name to varchar',
-  proname => 'varchar', prorettype => 'varchar', proargtypes => 'name',
+  proname => 'varchar', proleakproof => 't', prorettype => 'varchar', proargtypes => 'name',
   prosrc => 'name_text' },

 { oid => '1402', descr => 'current schema name',
@@ -3941,7 +3941,7 @@
   proname => 'macaddr8_or', prorettype => 'macaddr8',
   proargtypes => 'macaddr8 macaddr8', prosrc => 'macaddr8_or' },
 { oid => '4123', descr => 'convert macaddr to macaddr8',
-  proname => 'macaddr8', prorettype => 'macaddr8', proargtypes => 'macaddr',
+  proname => 'macaddr8', proleakproof => 't', prorettype => 'macaddr8', proargtypes => 'macaddr',
   prosrc => 'macaddrtomacaddr8' },
 { oid => '4124', descr => 'convert macaddr8 to macaddr',
   proname => 'macaddr', prorettype => 'macaddr', proargtypes => 'macaddr8',
@@ -4321,7 +4321,7 @@
   proname => 'trim_scale', prorettype => 'numeric', proargtypes => 'numeric',
   prosrc => 'numeric_trim_scale' },
 { oid => '1740', descr => 'convert int4 to numeric',
-  proname => 'numeric', prorettype => 'numeric', proargtypes => 'int4',
+  proname => 'numeric', proleakproof => 't', prorettype => 'numeric', proargtypes => 'int4',
   prosrc => 'int4_numeric' },
 { oid => '1741', descr => 'base 10 logarithm',
   proname => 'log', prolang => 'sql', prorettype => 'numeric',
@@ -4390,10 +4390,10 @@
   proname => 'int8', prorettype => 'int8', proargtypes => 'numeric',
   prosrc => 'numeric_int8' },
 { oid => '1781', descr => 'convert int8 to numeric',
-  proname => 'numeric', prorettype => 'numeric', proargtypes => 'int8',
+  proname => 'numeric', proleakproof => 't', prorettype => 'numeric', proargtypes => 'int8',
   prosrc => 'int8_numeric' },
 { oid => '1782', descr => 'convert int2 to numeric',
-  proname => 'numeric', prorettype => 'numeric', proargtypes => 'int2',
+  proname => 'numeric', proleakproof => 't', prorettype => 'numeric', proargtypes => 'int2',
   prosrc => 'int2_numeric' },
 { oid => '1783', descr => 'convert numeric to int2',
   proname => 'int2', prorettype => 'int2', proargtypes => 'numeric',
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 27056d70d3..bc1dafc796 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -572,6 +572,8 @@ int24ge(smallint,integer)
 int42ge(integer,smallint)
 oideq(oid,oid)
 oidne(oid,oid)
+float8(smallint)
+float4(smallint)
 nameeqtext(name,text)
 namelttext(name,text)
 nameletext(name,text)
@@ -610,6 +612,10 @@ float84lt(double precision,real)
 float84le(double precision,real)
 float84gt(double precision,real)
 float84ge(double precision,real)
+float8(real)
+int4(smallint)
+float8(integer)
+float4(integer)
 btint2cmp(smallint,smallint)
 btint4cmp(integer,integer)
 btfloat4cmp(real,real)
@@ -620,6 +626,9 @@ btnamecmp(name,name)
 bttextcmp(text,text)
 cash_cmp(money,money)
 btoidvectorcmp(oidvector,oidvector)
+text(name)
+name(text)
+name(character)
 text_larger(text,text)
 text_smaller(text,text)
 int8eq(bigint,bigint)
@@ -634,7 +643,10 @@ int84lt(bigint,integer)
 int84gt(bigint,integer)
 int84le(bigint,integer)
 int84ge(bigint,integer)
+int8(integer)
+float8(bigint)
 oidvectorne(oidvector,oidvector)
+float4(bigint)
 namelt(name,name)
 namele(name,name)
 namegt(name,name)
@@ -651,6 +663,7 @@ text_lt(text,text)
 text_le(text,text)
 text_gt(text,text)
 text_ge(text,text)
+int8(smallint)
 macaddr_eq(macaddr,macaddr)
 macaddr_lt(macaddr,macaddr)
 macaddr_le(macaddr,macaddr)
@@ -727,6 +740,9 @@ timetz_le(time with time zone,time with time zone)
 timetz_ge(time with time zone,time with time zone)
 timetz_gt(time with time zone,time with time zone)
 timetz_cmp(time with time zone,time with time zone)
+"interval"(time without time zone)
+name(character varying)
+"varchar"(name)
 circle_eq(circle,circle)
 circle_ne(circle,circle)
 circle_lt(circle,circle)
@@ -757,6 +773,9 @@ varbitcmp(bit varying,bit varying)
 boolle(boolean,boolean)
 boolge(boolean,boolean)
 btboolcmp(boolean,boolean)
+"numeric"(integer)
+"numeric"(bigint)
+"numeric"(smallint)
 int28eq(smallint,bigint)
 int28ne(smallint,bigint)
 int28lt(smallint,bigint)
@@ -837,6 +856,7 @@ macaddr8_gt(macaddr8,macaddr8)
 macaddr8_ge(macaddr8,macaddr8)
 macaddr8_ne(macaddr8,macaddr8)
 macaddr8_cmp(macaddr8,macaddr8)
+macaddr8(macaddr)
 xid8lt(xid8,xid8)
 xid8gt(xid8,xid8)
 xid8le(xid8,xid8)

Re: Mark unconditionally-safe implicit coercions as leakproof

От
Robert Haas
Дата:
On Fri, Jul 24, 2020 at 12:17 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> I went through the system's built-in implicit coercions to see
> which ones are unconditionally successful.  These could all be
> marked leakproof, as per attached patch.  This came up in the
> context of the nearby discussion about CASE, but it seems like
> an independent improvement.  If you have a function f(int8)
> that is leakproof, you don't want it to effectively become
> non-leakproof when you apply it to an int4 or int2 column.
>
> One that I didn't mark leakproof is rtrim1(), which is the
> infrastructure for char(n) to text coercion.  It looks like it
> actually does qualify right now, but the code is long enough and
> complex enough that I think such a marking would be a bit unsafe.
>
> Any objections?

IMHO, this is a nice improvement.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: Mark unconditionally-safe implicit coercions as leakproof

От
Tom Lane
Дата:
Robert Haas <robertmhaas@gmail.com> writes:
> On Fri, Jul 24, 2020 at 12:17 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> I went through the system's built-in implicit coercions to see
>> which ones are unconditionally successful.  These could all be
>> marked leakproof, as per attached patch.

> IMHO, this is a nice improvement.

Thanks; pushed.  On second reading I found that there are a few
non-implicit coercions that could usefully be marked leakproof
as well --- notably float4_numeric and float8_numeric, which should
be error-free now that infinities can be converted.

            regards, tom lane