Commit 6ca547cf authored by Tom Lane's avatar Tom Lane

Mark factorial operator, and postfix operators in general, as deprecated.

Per discussion, we're planning to remove parser support for postfix
operators in order to simplify the grammar.  So it behooves us to
put out a deprecation notice at least one release before that.

There is only one built-in postfix operator, ! for factorial.
Label it deprecated in the docs and in pg_description, and adjust
some examples that formerly relied on it.  (The sister prefix
operator !! is also deprecated.  We don't really have to remove
that one, but since we're suggesting that people use factorial()
instead, it seems better to remove both operators.)

Also state in the CREATE OPERATOR ref page that postfix operators
in general are going away.

Although this changes the initial contents of pg_description,
I did not force a catversion bump; it doesn't seem essential.

In v13, also back-patch 4c5cf543, so that there's someplace for
the <link>s to point to.

Mark Dilger and John Naylor, with some adjustments by me

Discussion: https://postgr.es/m/BE2DF53D-251A-4E26-972F-930E523580E9@enterprisedb.com
parent 3d351d91
...@@ -1055,6 +1055,7 @@ repeat('Pg', 4) <returnvalue>PgPgPgPg</returnvalue> ...@@ -1055,6 +1055,7 @@ repeat('Pg', 4) <returnvalue>PgPgPgPg</returnvalue>
</para> </para>
<para> <para>
Factorial Factorial
(deprecated, use <link linkend="function-factorial"><function>factorial()</function></link> instead)
</para> </para>
<para> <para>
<literal>5 !</literal> <literal>5 !</literal>
...@@ -1068,7 +1069,8 @@ repeat('Pg', 4) <returnvalue>PgPgPgPg</returnvalue> ...@@ -1068,7 +1069,8 @@ repeat('Pg', 4) <returnvalue>PgPgPgPg</returnvalue>
<returnvalue>numeric</returnvalue> <returnvalue>numeric</returnvalue>
</para> </para>
<para> <para>
Factorial (as a prefix operator) Factorial as a prefix operator
(deprecated, use <link linkend="function-factorial"><function>factorial()</function></link> instead)
</para> </para>
<para> <para>
<literal>!! 5</literal> <literal>!! 5</literal>
...@@ -1349,7 +1351,7 @@ repeat('Pg', 4) <returnvalue>PgPgPgPg</returnvalue> ...@@ -1349,7 +1351,7 @@ repeat('Pg', 4) <returnvalue>PgPgPgPg</returnvalue>
<row> <row>
<entry role="func_table_entry"><para role="func_signature"> <entry role="func_table_entry"><para role="func_signature">
<indexterm> <indexterm id="function-factorial">
<primary>factorial</primary> <primary>factorial</primary>
</indexterm> </indexterm>
<function>factorial</function> ( <type>bigint</type> ) <function>factorial</function> ( <type>bigint</type> )
......
...@@ -87,11 +87,18 @@ CREATE OPERATOR <replaceable>name</replaceable> ( ...@@ -87,11 +87,18 @@ CREATE OPERATOR <replaceable>name</replaceable> (
<para> <para>
At least one of <literal>LEFTARG</literal> and <literal>RIGHTARG</literal> must be defined. For At least one of <literal>LEFTARG</literal> and <literal>RIGHTARG</literal> must be defined. For
binary operators, both must be defined. For right unary binary operators, both must be defined. For right unary
operators, only <literal>LEFTARG</literal> should be defined, while for left operators, only <literal>LEFTARG</literal> should be defined, while for left
unary operators only <literal>RIGHTARG</literal> should be defined. unary operators only <literal>RIGHTARG</literal> should be defined.
</para> </para>
<note>
<para>
Right unary, also called postfix, operators are deprecated and will be
removed in <productname>PostgreSQL</productname> version 14.
</para>
</note>
<para> <para>
The <replaceable class="parameter">function_name</replaceable> The <replaceable class="parameter">function_name</replaceable>
function must have been previously defined using <command>CREATE function must have been previously defined using <command>CREATE
......
...@@ -977,27 +977,8 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) ...@@ -977,27 +977,8 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
Most operators have the same precedence and are left-associative. Most operators have the same precedence and are left-associative.
The precedence and associativity of the operators is hard-wired The precedence and associativity of the operators is hard-wired
into the parser. into the parser.
</para> Add parentheses if you want an expression with multiple operators
to be parsed in some other way than what the precedence rules imply.
<para>
You will
sometimes need to add parentheses when using combinations of
binary and unary operators. For instance:
<programlisting>
SELECT 5 ! - 6;
</programlisting>
will be parsed as:
<programlisting>
SELECT 5 ! (- 6);
</programlisting>
because the parser has no idea &mdash; until it is too late
&mdash; that <token>!</token> is defined as a postfix operator,
not an infix one. To get the desired behavior in this case, you
must write:
<programlisting>
SELECT (5 !) - 6;
</programlisting>
This is the price one pays for extensibility.
</para> </para>
<table id="sql-precedence-table"> <table id="sql-precedence-table">
......
...@@ -354,20 +354,19 @@ Some examples follow. ...@@ -354,20 +354,19 @@ Some examples follow.
</para> </para>
<example> <example>
<title>Factorial Operator Type Resolution</title> <title>Square Root Operator Type Resolution</title>
<para> <para>
There is only one factorial operator (postfix <literal>!</literal>) There is only one square root operator (prefix <literal>|/</literal>)
defined in the standard catalog, and it takes an argument of type defined in the standard catalog, and it takes an argument of type
<type>bigint</type>. <type>double precision</type>.
The scanner assigns an initial type of <type>integer</type> to the argument The scanner assigns an initial type of <type>integer</type> to the argument
in this query expression: in this query expression:
<screen> <screen>
SELECT 40 ! AS "40 factorial"; SELECT |/ 40 AS "square root of 40";
square root of 40
40 factorial -------------------
-------------------------------------------------- 6.324555320336759
815915283247897734345611269596115894272000000000
(1 row) (1 row)
</screen> </screen>
...@@ -375,7 +374,7 @@ So the parser does a type conversion on the operand and the query ...@@ -375,7 +374,7 @@ So the parser does a type conversion on the operand and the query
is equivalent to: is equivalent to:
<screen> <screen>
SELECT CAST(40 AS bigint) ! AS "40 factorial"; SELECT |/ CAST(40 AS double precision) AS "square root of 40";
</screen> </screen>
</para> </para>
</example> </example>
......
...@@ -218,10 +218,10 @@ ...@@ -218,10 +218,10 @@
oprname => '>=', oprleft => 'xid8', oprright => 'xid8', oprresult => 'bool', oprname => '>=', oprleft => 'xid8', oprright => 'xid8', oprresult => 'bool',
oprcom => '<=(xid8,xid8)', oprnegate => '<(xid8,xid8)', oprcode => 'xid8ge', oprcom => '<=(xid8,xid8)', oprnegate => '<(xid8,xid8)', oprcode => 'xid8ge',
oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' }, oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
{ oid => '388', descr => 'factorial', { oid => '388', descr => 'deprecated, use factorial() instead',
oprname => '!', oprkind => 'r', oprleft => 'int8', oprright => '0', oprname => '!', oprkind => 'r', oprleft => 'int8', oprright => '0',
oprresult => 'numeric', oprcode => 'numeric_fac' }, oprresult => 'numeric', oprcode => 'numeric_fac' },
{ oid => '389', descr => 'deprecated, use ! instead', { oid => '389', descr => 'deprecated, use factorial() instead',
oprname => '!!', oprkind => 'l', oprleft => '0', oprright => 'int8', oprname => '!!', oprkind => 'l', oprleft => '0', oprright => 'int8',
oprresult => 'numeric', oprcode => 'numeric_fac' }, oprresult => 'numeric', oprcode => 'numeric_fac' },
{ oid => '385', descr => 'equal', { oid => '385', descr => 'equal',
......
...@@ -328,6 +328,7 @@ ...@@ -328,6 +328,7 @@
proname => 'unknownout', prorettype => 'cstring', proargtypes => 'unknown', proname => 'unknownout', prorettype => 'cstring', proargtypes => 'unknown',
prosrc => 'unknownout' }, prosrc => 'unknownout' },
{ oid => '111', { oid => '111',
descr => 'implementation of deprecated ! and !! factorial operators',
proname => 'numeric_fac', prorettype => 'numeric', proargtypes => 'int8', proname => 'numeric_fac', prorettype => 'numeric', proargtypes => 'int8',
prosrc => 'numeric_fac' }, prosrc => 'numeric_fac' },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment