mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
Remove factorial operators, leaving only the factorial() function.
The "!" operator is our only built-in postfix operator. Remove it, on the way to removal of grammar support for postfix operators. There is also a "!!" prefix operator, but since it's been marked deprecated for most of its existence, we might as well remove it too. Also zap the SQL alias function numeric_fac(), which seems to have equally little reason to live. Mark Dilger, based on work by myself and Robert Haas; review by John Naylor Discussion: https://postgr.es/m/38ca86db-42ab-9b48-2902-337a0d6b8311@2ndquadrant.com
This commit is contained in:
parent
74d4608f50
commit
76f412ab31
@ -653,14 +653,6 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- Op
|
|||||||
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = (- "C 1")))
|
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = (- "C 1")))
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE 1 = c1!; -- OpExpr(r)
|
|
||||||
QUERY PLAN
|
|
||||||
----------------------------------------------------------------------------------------------------------
|
|
||||||
Foreign Scan on public.ft1 t1
|
|
||||||
Output: c1, c2, c3, c4, c5, c6, c7, c8
|
|
||||||
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((1::numeric = ("C 1" !)))
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr
|
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
--------------------------------------------------------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -307,7 +307,6 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NULL; -- Nu
|
|||||||
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NOT NULL; -- NullTest
|
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NOT NULL; -- NullTest
|
||||||
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr
|
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr
|
||||||
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- OpExpr(l)
|
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- OpExpr(l)
|
||||||
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE 1 = c1!; -- OpExpr(r)
|
|
||||||
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr
|
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr
|
||||||
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr
|
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr
|
||||||
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- SubscriptingRef
|
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- SubscriptingRef
|
||||||
|
@ -1048,36 +1048,6 @@ repeat('Pg', 4) <returnvalue>PgPgPgPg</returnvalue>
|
|||||||
</para></entry>
|
</para></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry role="func_table_entry"><para role="func_signature">
|
|
||||||
<type>bigint</type> <literal>!</literal>
|
|
||||||
<returnvalue>numeric</returnvalue>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Factorial
|
|
||||||
(deprecated, use <link linkend="function-factorial"><function>factorial()</function></link> instead)
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<literal>5 !</literal>
|
|
||||||
<returnvalue>120</returnvalue>
|
|
||||||
</para></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry role="func_table_entry"><para role="func_signature">
|
|
||||||
<literal>!!</literal> <type>bigint</type>
|
|
||||||
<returnvalue>numeric</returnvalue>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Factorial as a prefix operator
|
|
||||||
(deprecated, use <link linkend="function-factorial"><function>factorial()</function></link> instead)
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<literal>!! 5</literal>
|
|
||||||
<returnvalue>120</returnvalue>
|
|
||||||
</para></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry role="func_table_entry"><para role="func_signature">
|
<entry role="func_table_entry"><para role="func_signature">
|
||||||
<literal>@</literal> <replaceable>numeric_type</replaceable>
|
<literal>@</literal> <replaceable>numeric_type</replaceable>
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
/* FIXME: bump this before pushing! */
|
#define CATALOG_VERSION_NO 202009171
|
||||||
#define CATALOG_VERSION_NO 202009031
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -218,12 +218,6 @@
|
|||||||
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 => 'deprecated, use factorial() instead',
|
|
||||||
oprname => '!', oprkind => 'r', oprleft => 'int8', oprright => '0',
|
|
||||||
oprresult => 'numeric', oprcode => 'numeric_fac' },
|
|
||||||
{ oid => '389', descr => 'deprecated, use factorial() instead',
|
|
||||||
oprname => '!!', oprkind => 'l', oprleft => '0', oprright => 'int8',
|
|
||||||
oprresult => 'numeric', oprcode => 'numeric_fac' },
|
|
||||||
{ oid => '385', descr => 'equal',
|
{ oid => '385', descr => 'equal',
|
||||||
oprname => '=', oprcanhash => 't', oprleft => 'cid', oprright => 'cid',
|
oprname => '=', oprcanhash => 't', oprleft => 'cid', oprright => 'cid',
|
||||||
oprresult => 'bool', oprcom => '=(cid,cid)', oprcode => 'cideq',
|
oprresult => 'bool', oprcom => '=(cid,cid)', oprcode => 'cideq',
|
||||||
|
@ -327,10 +327,6 @@
|
|||||||
{ oid => '110', descr => 'I/O',
|
{ oid => '110', descr => 'I/O',
|
||||||
proname => 'unknownout', prorettype => 'cstring', proargtypes => 'unknown',
|
proname => 'unknownout', prorettype => 'cstring', proargtypes => 'unknown',
|
||||||
prosrc => 'unknownout' },
|
prosrc => 'unknownout' },
|
||||||
{ oid => '111',
|
|
||||||
descr => 'implementation of deprecated ! and !! factorial operators',
|
|
||||||
proname => 'numeric_fac', prorettype => 'numeric', proargtypes => 'int8',
|
|
||||||
prosrc => 'numeric_fac' },
|
|
||||||
|
|
||||||
{ oid => '115',
|
{ oid => '115',
|
||||||
proname => 'box_above_eq', prorettype => 'bool', proargtypes => 'box box',
|
proname => 'box_above_eq', prorettype => 'bool', proargtypes => 'box box',
|
||||||
|
@ -16,15 +16,15 @@ CREATE OPERATOR <% (
|
|||||||
);
|
);
|
||||||
CREATE OPERATOR @#@ (
|
CREATE OPERATOR @#@ (
|
||||||
rightarg = int8, -- left unary
|
rightarg = int8, -- left unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
CREATE OPERATOR #@# (
|
CREATE OPERATOR #@# (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
CREATE OPERATOR #%# (
|
CREATE OPERATOR #%# (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
-- Test operator created above
|
-- Test operator created above
|
||||||
SELECT point '(1,2)' <% widget '(0,0,3)' AS t,
|
SELECT point '(1,2)' <% widget '(0,0,3)' AS t,
|
||||||
@ -40,7 +40,7 @@ ERROR: operator does not exist: integer ######
|
|||||||
-- => is disallowed now
|
-- => is disallowed now
|
||||||
CREATE OPERATOR => (
|
CREATE OPERATOR => (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
ERROR: syntax error at or near "=>"
|
ERROR: syntax error at or near "=>"
|
||||||
LINE 1: CREATE OPERATOR => (
|
LINE 1: CREATE OPERATOR => (
|
||||||
@ -50,7 +50,7 @@ LINE 1: CREATE OPERATOR => (
|
|||||||
-- this is legal because ! is not allowed in sql ops
|
-- this is legal because ! is not allowed in sql ops
|
||||||
CREATE OPERATOR !=- (
|
CREATE OPERATOR !=- (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
SELECT 2 !=-;
|
SELECT 2 !=-;
|
||||||
?column?
|
?column?
|
||||||
@ -128,7 +128,7 @@ REVOKE USAGE ON SCHEMA schema_op1 FROM regress_rol_op1;
|
|||||||
SET ROLE regress_rol_op1;
|
SET ROLE regress_rol_op1;
|
||||||
CREATE OPERATOR schema_op1.#*# (
|
CREATE OPERATOR schema_op1.#*# (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
ERROR: permission denied for schema schema_op1
|
ERROR: permission denied for schema schema_op1
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
@ -136,7 +136,7 @@ ROLLBACK;
|
|||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
CREATE OPERATOR #*# (
|
CREATE OPERATOR #*# (
|
||||||
leftarg = SETOF int8,
|
leftarg = SETOF int8,
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
ERROR: SETOF type not allowed for operator argument
|
ERROR: SETOF type not allowed for operator argument
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
@ -144,7 +144,7 @@ ROLLBACK;
|
|||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
CREATE OPERATOR #*# (
|
CREATE OPERATOR #*# (
|
||||||
rightarg = SETOF int8,
|
rightarg = SETOF int8,
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
ERROR: SETOF type not allowed for operator argument
|
ERROR: SETOF type not allowed for operator argument
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
@ -168,13 +168,13 @@ ROLLBACK;
|
|||||||
-- Should fail. Invalid attribute
|
-- Should fail. Invalid attribute
|
||||||
CREATE OPERATOR #@%# (
|
CREATE OPERATOR #@%# (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac,
|
procedure = factorial,
|
||||||
invalid_att = int8
|
invalid_att = int8
|
||||||
);
|
);
|
||||||
WARNING: operator attribute "invalid_att" not recognized
|
WARNING: operator attribute "invalid_att" not recognized
|
||||||
-- Should fail. At least leftarg or rightarg should be mandatorily specified
|
-- Should fail. At least leftarg or rightarg should be mandatorily specified
|
||||||
CREATE OPERATOR #@%# (
|
CREATE OPERATOR #@%# (
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
ERROR: at least one of leftarg or rightarg must be specified
|
ERROR: at least one of leftarg or rightarg must be specified
|
||||||
-- Should fail. Procedure should be mandatorily specified
|
-- Should fail. Procedure should be mandatorily specified
|
||||||
|
@ -2972,34 +2972,26 @@ ERROR: value overflows numeric format
|
|||||||
--
|
--
|
||||||
-- Tests for factorial
|
-- Tests for factorial
|
||||||
--
|
--
|
||||||
SELECT 4!;
|
SELECT factorial(4);
|
||||||
?column?
|
factorial
|
||||||
----------
|
-----------
|
||||||
24
|
24
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT !!3;
|
|
||||||
?column?
|
|
||||||
----------
|
|
||||||
6
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT factorial(15);
|
SELECT factorial(15);
|
||||||
factorial
|
factorial
|
||||||
---------------
|
---------------
|
||||||
1307674368000
|
1307674368000
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT 100000!;
|
SELECT factorial(100000);
|
||||||
ERROR: value overflows numeric format
|
ERROR: value overflows numeric format
|
||||||
SELECT 0!;
|
SELECT factorial(0);
|
||||||
?column?
|
factorial
|
||||||
----------
|
-----------
|
||||||
1
|
1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT -4!;
|
|
||||||
ERROR: factorial of a negative number is undefined
|
|
||||||
SELECT factorial(-4);
|
SELECT factorial(-4);
|
||||||
ERROR: factorial of a negative number is undefined
|
ERROR: factorial of a negative number is undefined
|
||||||
--
|
--
|
||||||
|
@ -19,17 +19,17 @@ CREATE OPERATOR <% (
|
|||||||
|
|
||||||
CREATE OPERATOR @#@ (
|
CREATE OPERATOR @#@ (
|
||||||
rightarg = int8, -- left unary
|
rightarg = int8, -- left unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE OPERATOR #@# (
|
CREATE OPERATOR #@# (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE OPERATOR #%# (
|
CREATE OPERATOR #%# (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Test operator created above
|
-- Test operator created above
|
||||||
@ -42,7 +42,7 @@ COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad right unary';
|
|||||||
-- => is disallowed now
|
-- => is disallowed now
|
||||||
CREATE OPERATOR => (
|
CREATE OPERATOR => (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
|
|
||||||
-- lexing of <=, >=, <>, != has a number of edge cases
|
-- lexing of <=, >=, <>, != has a number of edge cases
|
||||||
@ -51,7 +51,7 @@ CREATE OPERATOR => (
|
|||||||
-- this is legal because ! is not allowed in sql ops
|
-- this is legal because ! is not allowed in sql ops
|
||||||
CREATE OPERATOR !=- (
|
CREATE OPERATOR !=- (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
SELECT 2 !=-;
|
SELECT 2 !=-;
|
||||||
-- make sure lexer returns != as <> even in edge cases
|
-- make sure lexer returns != as <> even in edge cases
|
||||||
@ -85,7 +85,7 @@ REVOKE USAGE ON SCHEMA schema_op1 FROM regress_rol_op1;
|
|||||||
SET ROLE regress_rol_op1;
|
SET ROLE regress_rol_op1;
|
||||||
CREATE OPERATOR schema_op1.#*# (
|
CREATE OPERATOR schema_op1.#*# (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ ROLLBACK;
|
|||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
CREATE OPERATOR #*# (
|
CREATE OPERATOR #*# (
|
||||||
leftarg = SETOF int8,
|
leftarg = SETOF int8,
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ ROLLBACK;
|
|||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
CREATE OPERATOR #*# (
|
CREATE OPERATOR #*# (
|
||||||
rightarg = SETOF int8,
|
rightarg = SETOF int8,
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
|
||||||
@ -129,13 +129,13 @@ ROLLBACK;
|
|||||||
-- Should fail. Invalid attribute
|
-- Should fail. Invalid attribute
|
||||||
CREATE OPERATOR #@%# (
|
CREATE OPERATOR #@%# (
|
||||||
leftarg = int8, -- right unary
|
leftarg = int8, -- right unary
|
||||||
procedure = numeric_fac,
|
procedure = factorial,
|
||||||
invalid_att = int8
|
invalid_att = int8
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Should fail. At least leftarg or rightarg should be mandatorily specified
|
-- Should fail. At least leftarg or rightarg should be mandatorily specified
|
||||||
CREATE OPERATOR #@%# (
|
CREATE OPERATOR #@%# (
|
||||||
procedure = numeric_fac
|
procedure = factorial
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Should fail. Procedure should be mandatorily specified
|
-- Should fail. Procedure should be mandatorily specified
|
||||||
|
@ -1300,12 +1300,10 @@ SELECT lcm(9999 * (10::numeric)^131068 + (10::numeric^131068 - 1), 2); -- overfl
|
|||||||
--
|
--
|
||||||
-- Tests for factorial
|
-- Tests for factorial
|
||||||
--
|
--
|
||||||
SELECT 4!;
|
SELECT factorial(4);
|
||||||
SELECT !!3;
|
|
||||||
SELECT factorial(15);
|
SELECT factorial(15);
|
||||||
SELECT 100000!;
|
SELECT factorial(100000);
|
||||||
SELECT 0!;
|
SELECT factorial(0);
|
||||||
SELECT -4!;
|
|
||||||
SELECT factorial(-4);
|
SELECT factorial(-4);
|
||||||
|
|
||||||
--
|
--
|
||||||
|
Loading…
x
Reference in New Issue
Block a user