aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-05-01 18:53:52 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-05-01 18:53:52 +0000
commitb4349519c178b2b46cc42872a28d896291b6464e (patch)
tree4aeacf2228a6df440ad4ca33d1c554e2e125e9fa
parentc4320619635800a6116a02eee08b232c5abea266 (diff)
downloadpostgresql-b4349519c178b2b46cc42872a28d896291b6464e.tar.gz
postgresql-b4349519c178b2b46cc42872a28d896291b6464e.zip
Fix a thinko in my patch of a couple months ago for bug #3116: it did the
wrong thing when inlining polymorphic SQL functions, because it was using the function's declared return type where it should have used the actual result type of the current call. In 8.1 and 8.2 this causes obvious failures even if you don't have assertions turned on; in 8.0 and 7.4 it would only be a problem if the inlined expression were used as an input to a function that did run-time type determination on its inputs. Add a regression test, since this is evidently an under-tested area.
-rw-r--r--src/backend/optimizer/util/clauses.c8
-rw-r--r--src/test/regress/expected/polymorphism.out35
-rw-r--r--src/test/regress/sql/polymorphism.sql16
3 files changed, 55 insertions, 4 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 417cecff8e9..5233a338e6f 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.243 2007/04/30 00:14:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.244 2007/05/01 18:53:51 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -3063,11 +3063,11 @@ inline_function(Oid funcid, Oid result_type, List *args,
* compatible with the original expression result type. To avoid
* confusing matters, insert a RelabelType in such cases.
*/
- if (exprType(newexpr) != funcform->prorettype)
+ if (exprType(newexpr) != result_type)
{
- Assert(IsBinaryCoercible(exprType(newexpr), funcform->prorettype));
+ Assert(IsBinaryCoercible(exprType(newexpr), result_type));
newexpr = (Node *) makeRelabelType((Expr *) newexpr,
- funcform->prorettype,
+ result_type,
-1,
COERCE_IMPLICIT_CAST);
}
diff --git a/src/test/regress/expected/polymorphism.out b/src/test/regress/expected/polymorphism.out
index 29a0a190d61..de393a05288 100644
--- a/src/test/regress/expected/polymorphism.out
+++ b/src/test/regress/expected/polymorphism.out
@@ -542,3 +542,38 @@ select mysum2(f1, f1 + 1) from t;
38
(1 row)
+-- test inlining of polymorphic SQL functions
+create function bleat(int) returns int as $$
+begin
+ raise notice 'bleat %', $1;
+ return $1;
+end$$ language plpgsql;
+create function sql_if(bool, anyelement, anyelement) returns anyelement as $$
+select case when $1 then $2 else $3 end $$ language sql;
+-- Note this would fail with integer overflow, never mind wrong bleat() output,
+-- if the CASE expression were not successfully inlined
+select f1, sql_if(f1 > 0, bleat(f1), bleat(f1 + 1)) from int4_tbl;
+NOTICE: bleat 1
+NOTICE: bleat 123456
+NOTICE: bleat -123455
+NOTICE: bleat 2147483647
+NOTICE: bleat -2147483646
+ f1 | sql_if
+-------------+-------------
+ 0 | 1
+ 123456 | 123456
+ -123456 | -123455
+ 2147483647 | 2147483647
+ -2147483647 | -2147483646
+(5 rows)
+
+select q2, sql_if(q2 > 0, q2, q2 + 1) from int8_tbl;
+ q2 | sql_if
+-------------------+-------------------
+ 456 | 456
+ 4567890123456789 | 4567890123456789
+ 123 | 123
+ 4567890123456789 | 4567890123456789
+ -4567890123456789 | -4567890123456788
+(5 rows)
+
diff --git a/src/test/regress/sql/polymorphism.sql b/src/test/regress/sql/polymorphism.sql
index 218a0a72b38..c2bf14b48f0 100644
--- a/src/test/regress/sql/polymorphism.sql
+++ b/src/test/regress/sql/polymorphism.sql
@@ -374,3 +374,19 @@ select f3, myaggn08b(f1) from t group by f3;
select f3, myaggn09a(f1) from t group by f3;
select f3, myaggn10a(f1) from t group by f3;
select mysum2(f1, f1 + 1) from t;
+
+-- test inlining of polymorphic SQL functions
+create function bleat(int) returns int as $$
+begin
+ raise notice 'bleat %', $1;
+ return $1;
+end$$ language plpgsql;
+
+create function sql_if(bool, anyelement, anyelement) returns anyelement as $$
+select case when $1 then $2 else $3 end $$ language sql;
+
+-- Note this would fail with integer overflow, never mind wrong bleat() output,
+-- if the CASE expression were not successfully inlined
+select f1, sql_if(f1 > 0, bleat(f1), bleat(f1 + 1)) from int4_tbl;
+
+select q2, sql_if(q2 > 0, q2, q2 + 1) from int8_tbl;