Re: pg_get_constraintdef() doesn't always give an equal constraint - Mailing list pgsql-bugs

From Tom Lane
Subject Re: pg_get_constraintdef() doesn't always give an equal constraint
Date
Msg-id 14244.1427569696@sss.pgh.pa.us
Whole thread Raw
In response to Re: pg_get_constraintdef() doesn't always give an equal constraint  (Jeff Davis <pgsql@j-davis.com>)
Responses Re: pg_get_constraintdef() doesn't always give an equal constraint  (Jeff Davis <pgsql@j-davis.com>)
List pgsql-bugs
Jeff Davis <pgsql@j-davis.com> writes:
> On Mon, Mar 23, 2015 at 7:32 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> I don't see any simple way around that except to dump using the syntax
>> '10.1'::double precision

> There is a similar problem related to NUMERIC:
>   '1'::numeric is dumped as
>   1::numeric
> which introduces a cast as well. There's also a problem with negative
> constants, because it introduces parenthesis instead of single quotes:
>   '-1'::numeric
> is dumped as
>   (-1)::numeric

Yeah.  In general, this code was trying to produce something nice-looking
and semantically equivalent, but not necessarily something that would
re-parse as the exact same Const node.

> This bug is pretty old and nobody has complained about it before.
> Let's just figure out a good unambiguous representation of float and
> numeric literals, and then backport it. Anyone who cares enough to fix
> this issue can upgrade to the latest point release on the old version,
> and then dump/reload.

> For numeric, I think appending ".0" (if it's an integral value) is the
> easiest, prettiest, and least-surprising.

... and wrong, because that would affect the dscale.  I don't think we
want this code editorializing on the printed format in any case.

> For floats, we can either
> use the single-quotes and type annotation, or we can come up with
> something new like appending an "f" to the value.

I cannot see back-porting anything as invasive as changing the lexer.

Basically, I think we have to change ruleutils so that it quotes anything
that wouldn't be seen as a simple integer or numeric constant by the
lexer+grammar.

The attached patch does this; the regression test changes illustrate
what's going to happen to the output if we do this.

Looking at the changes, I'm not 100% convinced we want to back-patch.
As you say, nobody's complained of this problem before, and I'm worried
that people will see the output changes as a bigger deal than the issue
we're trying to fix.

Thoughts?

            regards, tom lane

(PS: I've not checked contrib or pl tests, so this patch may be incomplete
as far as expected-output changes go.)

diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 28e1acf..4672cf5 100644
*** a/src/backend/utils/adt/ruleutils.c
--- b/src/backend/utils/adt/ruleutils.c
***************
*** 15,20 ****
--- 15,21 ----
   */
  #include "postgres.h"

+ #include <ctype.h>
  #include <unistd.h>
  #include <fcntl.h>

*************** get_const_expr(Const *constval, deparse_
*** 8018,8025 ****
      Oid            typoutput;
      bool        typIsVarlena;
      char       *extval;
!     bool        isfloat = false;
!     bool        needlabel;

      if (constval->constisnull)
      {
--- 8019,8025 ----
      Oid            typoutput;
      bool        typIsVarlena;
      char       *extval;
!     bool        needlabel = false;

      if (constval->constisnull)
      {
*************** get_const_expr(Const *constval, deparse_
*** 8045,8084 ****

      switch (constval->consttype)
      {
-         case INT2OID:
          case INT4OID:
!         case INT8OID:
!         case OIDOID:
!         case FLOAT4OID:
!         case FLOAT8OID:
          case NUMERICOID:
              {
!                 /*
!                  * These types are printed without quotes unless they contain
!                  * values that aren't accepted by the scanner unquoted (e.g.,
!                  * 'NaN').  Note that strtod() and friends might accept NaN,
!                  * so we can't use that to test.
!                  *
!                  * In reality we only need to defend against infinity and NaN,
!                  * so we need not get too crazy about pattern matching here.
!                  *
!                  * There is a special-case gotcha: if the constant is signed,
!                  * we need to parenthesize it, else the parser might see a
!                  * leading plus/minus as binding less tightly than adjacent
!                  * operators --- particularly, the cast that we might attach
!                  * below.
!                  */
!                 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
!                 {
!                     if (extval[0] == '+' || extval[0] == '-')
!                         appendStringInfo(buf, "(%s)", extval);
!                     else
!                         appendStringInfoString(buf, extval);
!                     if (strcspn(extval, "eE.") != strlen(extval))
!                         isfloat = true; /* it looks like a float */
!                 }
!                 else
!                     appendStringInfo(buf, "'%s'", extval);
              }
              break;

--- 8045,8086 ----

      switch (constval->consttype)
      {
          case INT4OID:
!
!             /*
!              * INT4 can be printed without any decoration, unless it is
!              * negative; in that case print it as '-nnn'::integer to ensure
!              * that the output will re-parse as a constant, not as a constant
!              * plus operator.  In most cases we could get away with printing
!              * (-nnn) instead, because of the way that gram.y handles negative
!              * literals; but that doesn't work for INT_MIN, and it doesn't
!              * seem that much prettier anyway.
!              */
!             if (extval[0] != '-')
!                 appendStringInfoString(buf, extval);
!             else
!             {
!                 appendStringInfo(buf, "'%s'", extval);
!                 needlabel = true;        /* we must attach a cast */
!             }
!             break;
!
          case NUMERICOID:
+
+             /*
+              * NUMERIC can be printed without quotes if it looks like a float
+              * constant (not an integer, and not Infinity or NaN) and doesn't
+              * have a leading sign (for the same reason as for INT4).
+              */
+             if (isdigit((unsigned char) extval[0]) &&
+                 strcspn(extval, "eE.") != strlen(extval))
              {
!                 appendStringInfoString(buf, extval);
!             }
!             else
!             {
!                 appendStringInfo(buf, "'%s'", extval);
!                 needlabel = true;        /* we must attach a cast */
              }
              break;

*************** get_const_expr(Const *constval, deparse_
*** 8114,8131 ****
      switch (constval->consttype)
      {
          case BOOLOID:
-         case INT4OID:
          case UNKNOWNOID:
              /* These types can be left unlabeled */
              needlabel = false;
              break;
          case NUMERICOID:

              /*
               * Float-looking constants will be typed as numeric, but if
               * there's a specific typmod we need to show it.
               */
!             needlabel = !isfloat || (constval->consttypmod >= 0);
              break;
          default:
              needlabel = true;
--- 8116,8135 ----
      switch (constval->consttype)
      {
          case BOOLOID:
          case UNKNOWNOID:
              /* These types can be left unlabeled */
              needlabel = false;
              break;
+         case INT4OID:
+             /* We determined above whether a label is needed */
+             break;
          case NUMERICOID:

              /*
               * Float-looking constants will be typed as numeric, but if
               * there's a specific typmod we need to show it.
               */
!             needlabel |= (constval->consttypmod >= 0);
              break;
          default:
              needlabel = true;
diff --git a/src/test/regress/expected/equivclass.out b/src/test/regress/expected/equivclass.out
index dfae84e..0391b8e 100644
*** a/src/test/regress/expected/equivclass.out
--- b/src/test/regress/expected/equivclass.out
*************** set enable_mergejoin = off;
*** 104,114 ****
  --
  explain (costs off)
    select * from ec0 where ff = f1 and f1 = '42'::int8;
!             QUERY PLAN
! ----------------------------------
   Index Scan using ec0_pkey on ec0
!    Index Cond: (ff = 42::bigint)
!    Filter: (f1 = 42::bigint)
  (3 rows)

  explain (costs off)
--- 104,114 ----
  --
  explain (costs off)
    select * from ec0 where ff = f1 and f1 = '42'::int8;
!             QUERY PLAN
! -----------------------------------
   Index Scan using ec0_pkey on ec0
!    Index Cond: (ff = '42'::bigint)
!    Filter: (f1 = '42'::bigint)
  (3 rows)

  explain (costs off)
*************** explain (costs off)
*** 139,150 ****

  explain (costs off)
    select * from ec1, ec2 where ff = x1 and ff = '42'::int8;
!                           QUERY PLAN
! ---------------------------------------------------------------
   Nested Loop
     Join Filter: (ec1.ff = ec2.x1)
     ->  Index Scan using ec1_pkey on ec1
!          Index Cond: ((ff = 42::bigint) AND (ff = 42::bigint))
     ->  Seq Scan on ec2
  (5 rows)

--- 139,150 ----

  explain (costs off)
    select * from ec1, ec2 where ff = x1 and ff = '42'::int8;
!                             QUERY PLAN
! -------------------------------------------------------------------
   Nested Loop
     Join Filter: (ec1.ff = ec2.x1)
     ->  Index Scan using ec1_pkey on ec1
!          Index Cond: ((ff = '42'::bigint) AND (ff = '42'::bigint))
     ->  Seq Scan on ec2
  (5 rows)

*************** explain (costs off)
*** 161,174 ****

  explain (costs off)
    select * from ec1, ec2 where ff = x1 and '42'::int8 = x1;
!                QUERY PLAN
! ----------------------------------------
   Nested Loop
     Join Filter: (ec1.ff = ec2.x1)
     ->  Index Scan using ec1_pkey on ec1
!          Index Cond: (ff = 42::bigint)
     ->  Seq Scan on ec2
!          Filter: (42::bigint = x1)
  (6 rows)

  explain (costs off)
--- 161,174 ----

  explain (costs off)
    select * from ec1, ec2 where ff = x1 and '42'::int8 = x1;
!                QUERY PLAN
! -----------------------------------------
   Nested Loop
     Join Filter: (ec1.ff = ec2.x1)
     ->  Index Scan using ec1_pkey on ec1
!          Index Cond: (ff = '42'::bigint)
     ->  Seq Scan on ec2
!          Filter: ('42'::bigint = x1)
  (6 rows)

  explain (costs off)
*************** explain (costs off)
*** 210,216 ****
  -----------------------------------------------------
   Nested Loop
     ->  Index Scan using ec1_pkey on ec1
!          Index Cond: (ff = 42::bigint)
     ->  Append
           ->  Index Scan using ec1_expr2 on ec1 ec1_1
                 Index Cond: (((ff + 2) + 1) = ec1.f1)
--- 210,216 ----
  -----------------------------------------------------
   Nested Loop
     ->  Index Scan using ec1_pkey on ec1
!          Index Cond: (ff = '42'::bigint)
     ->  Append
           ->  Index Scan using ec1_expr2 on ec1 ec1_1
                 Index Cond: (((ff + 2) + 1) = ec1.f1)
*************** explain (costs off)
*** 229,248 ****
       union all
       select ff + 4 as x from ec1) as ss1
    where ss1.x = ec1.f1 and ec1.ff = 42::int8 and ec1.ff = ec1.f1;
!                           QUERY PLAN
! ---------------------------------------------------------------
   Nested Loop
     Join Filter: ((((ec1_1.ff + 2) + 1)) = ec1.f1)
     ->  Index Scan using ec1_pkey on ec1
!          Index Cond: ((ff = 42::bigint) AND (ff = 42::bigint))
           Filter: (ff = f1)
     ->  Append
           ->  Index Scan using ec1_expr2 on ec1 ec1_1
!                Index Cond: (((ff + 2) + 1) = 42::bigint)
           ->  Index Scan using ec1_expr3 on ec1 ec1_2
!                Index Cond: (((ff + 3) + 1) = 42::bigint)
           ->  Index Scan using ec1_expr4 on ec1 ec1_3
!                Index Cond: ((ff + 4) = 42::bigint)
  (12 rows)

  explain (costs off)
--- 229,248 ----
       union all
       select ff + 4 as x from ec1) as ss1
    where ss1.x = ec1.f1 and ec1.ff = 42::int8 and ec1.ff = ec1.f1;
!                             QUERY PLAN
! -------------------------------------------------------------------
   Nested Loop
     Join Filter: ((((ec1_1.ff + 2) + 1)) = ec1.f1)
     ->  Index Scan using ec1_pkey on ec1
!          Index Cond: ((ff = '42'::bigint) AND (ff = '42'::bigint))
           Filter: (ff = f1)
     ->  Append
           ->  Index Scan using ec1_expr2 on ec1 ec1_1
!                Index Cond: (((ff + 2) + 1) = '42'::bigint)
           ->  Index Scan using ec1_expr3 on ec1 ec1_2
!                Index Cond: (((ff + 3) + 1) = '42'::bigint)
           ->  Index Scan using ec1_expr4 on ec1 ec1_3
!                Index Cond: ((ff + 4) = '42'::bigint)
  (12 rows)

  explain (costs off)
*************** explain (costs off)
*** 265,271 ****
   Nested Loop
     ->  Nested Loop
           ->  Index Scan using ec1_pkey on ec1
!                Index Cond: (ff = 42::bigint)
           ->  Append
                 ->  Index Scan using ec1_expr2 on ec1 ec1_1
                       Index Cond: (((ff + 2) + 1) = ec1.f1)
--- 265,271 ----
   Nested Loop
     ->  Nested Loop
           ->  Index Scan using ec1_pkey on ec1
!                Index Cond: (ff = '42'::bigint)
           ->  Append
                 ->  Index Scan using ec1_expr2 on ec1 ec1_1
                       Index Cond: (((ff + 2) + 1) = ec1.f1)
*************** explain (costs off)
*** 321,327 ****
                       ->  Sort
                             Sort Key: ec1.f1 USING <
                             ->  Index Scan using ec1_pkey on ec1
!                                  Index Cond: (ff = 42::bigint)
  (20 rows)

  -- check partially indexed scan
--- 321,327 ----
                       ->  Sort
                             Sort Key: ec1.f1 USING <
                             ->  Index Scan using ec1_pkey on ec1
!                                  Index Cond: (ff = '42'::bigint)
  (20 rows)

  -- check partially indexed scan
*************** explain (costs off)
*** 341,347 ****
  -----------------------------------------------------
   Nested Loop
     ->  Index Scan using ec1_pkey on ec1
!          Index Cond: (ff = 42::bigint)
     ->  Append
           ->  Index Scan using ec1_expr2 on ec1 ec1_1
                 Index Cond: (((ff + 2) + 1) = ec1.f1)
--- 341,347 ----
  -----------------------------------------------------
   Nested Loop
     ->  Index Scan using ec1_pkey on ec1
!          Index Cond: (ff = '42'::bigint)
     ->  Append
           ->  Index Scan using ec1_expr2 on ec1 ec1_1
                 Index Cond: (((ff + 2) + 1) = ec1.f1)
*************** explain (costs off)
*** 378,383 ****
           ->  Sort
                 Sort Key: ec1.f1 USING <
                 ->  Index Scan using ec1_pkey on ec1
!                      Index Cond: (ff = 42::bigint)
  (14 rows)

--- 378,383 ----
           ->  Sort
                 Sort Key: ec1.f1 USING <
                 ->  Index Scan using ec1_pkey on ec1
!                      Index Cond: (ff = '42'::bigint)
  (14 rows)

diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 57fc910..046b085 100644
*** a/src/test/regress/expected/join.out
--- b/src/test/regress/expected/join.out
*************** SELECT qq, unique1
*** 2544,2559 ****
    ( SELECT COALESCE(q2, -1) AS qq FROM int8_tbl b ) AS ss2
    USING (qq)
    INNER JOIN tenk1 c ON qq = unique2;
!                                               QUERY PLAN
! -------------------------------------------------------------------------------------------------------
   Nested Loop
     ->  Hash Full Join
!          Hash Cond: (COALESCE(a.q1, 0::bigint) = COALESCE(b.q2, (-1)::bigint))
           ->  Seq Scan on int8_tbl a
           ->  Hash
                 ->  Seq Scan on int8_tbl b
     ->  Index Scan using tenk1_unique2 on tenk1 c
!          Index Cond: (unique2 = COALESCE((COALESCE(a.q1, 0::bigint)), (COALESCE(b.q2, (-1)::bigint))))
  (8 rows)

  SELECT qq, unique1
--- 2544,2559 ----
    ( SELECT COALESCE(q2, -1) AS qq FROM int8_tbl b ) AS ss2
    USING (qq)
    INNER JOIN tenk1 c ON qq = unique2;
!                                                QUERY PLAN
! ---------------------------------------------------------------------------------------------------------
   Nested Loop
     ->  Hash Full Join
!          Hash Cond: (COALESCE(a.q1, '0'::bigint) = COALESCE(b.q2, '-1'::bigint))
           ->  Seq Scan on int8_tbl a
           ->  Hash
                 ->  Seq Scan on int8_tbl b
     ->  Index Scan using tenk1_unique2 on tenk1 c
!          Index Cond: (unique2 = COALESCE((COALESCE(a.q1, '0'::bigint)), (COALESCE(b.q2, '-1'::bigint))))
  (8 rows)

  SELECT qq, unique1
*************** select * from
*** 3003,3012 ****
  ) ss
  where fault = 122
  order by fault;
!                            QUERY PLAN
! -----------------------------------------------------------------
   Nested Loop Left Join
!    Filter: ((COALESCE(tenk1.unique1, (-1)) + int8_tbl.q1) = 122)
     ->  Seq Scan on int8_tbl
     ->  Index Scan using tenk1_unique2 on tenk1
           Index Cond: (int8_tbl.q2 = unique2)
--- 3003,3012 ----
  ) ss
  where fault = 122
  order by fault;
!                                 QUERY PLAN
! --------------------------------------------------------------------------
   Nested Loop Left Join
!    Filter: ((COALESCE(tenk1.unique1, '-1'::integer) + int8_tbl.q1) = 122)
     ->  Seq Scan on int8_tbl
     ->  Index Scan using tenk1_unique2 on tenk1
           Index Cond: (int8_tbl.q2 = unique2)
*************** explain (verbose, costs off)
*** 4012,4025 ****
  select * from
    int8_tbl a left join
    lateral (select *, coalesce(a.q2, 42) as x from int8_tbl b) ss on a.q2 = ss.q1;
!                            QUERY PLAN
! ----------------------------------------------------------------
   Nested Loop Left Join
!    Output: a.q1, a.q2, b.q1, b.q2, (COALESCE(a.q2, 42::bigint))
     ->  Seq Scan on public.int8_tbl a
           Output: a.q1, a.q2
     ->  Seq Scan on public.int8_tbl b
!          Output: b.q1, b.q2, COALESCE(a.q2, 42::bigint)
           Filter: (a.q2 = b.q1)
  (7 rows)

--- 4012,4025 ----
  select * from
    int8_tbl a left join
    lateral (select *, coalesce(a.q2, 42) as x from int8_tbl b) ss on a.q2 = ss.q1;
!                             QUERY PLAN
! ------------------------------------------------------------------
   Nested Loop Left Join
!    Output: a.q1, a.q2, b.q1, b.q2, (COALESCE(a.q2, '42'::bigint))
     ->  Seq Scan on public.int8_tbl a
           Output: a.q1, a.q2
     ->  Seq Scan on public.int8_tbl b
!          Output: b.q1, b.q2, COALESCE(a.q2, '42'::bigint)
           Filter: (a.q2 = b.q1)
  (7 rows)

*************** select * from
*** 4235,4266 ****
      lateral (select q1, coalesce(ss1.x,q2) as y from int8_tbl d) ss2
    ) on c.q2 = ss2.q1,
    lateral (select ss2.y offset 0) ss3;
!                                                                                   QUERY PLAN
                                                        
!
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Nested Loop
!    Output: c.q1, c.q2, a.q1, a.q2, b.q1, (COALESCE(b.q2, 42::bigint)), d.q1, (COALESCE((COALESCE(b.q2, 42::bigint)),
d.q2)),((COALESCE((COALESCE(b.q2, 42::bigint)), d.q2))) 
     ->  Hash Right Join
!          Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, 42::bigint)), (COALESCE((COALESCE(b.q2,
42::bigint)),d.q2)) 
           Hash Cond: (d.q1 = c.q2)
           ->  Nested Loop
!                Output: a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, 42::bigint)), (COALESCE((COALESCE(b.q2, 42::bigint)),
d.q2))
                 ->  Hash Left Join
!                      Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, 42::bigint))
                       Hash Cond: (a.q2 = b.q1)
                       ->  Seq Scan on public.int8_tbl a
                             Output: a.q1, a.q2
                       ->  Hash
!                            Output: b.q1, (COALESCE(b.q2, 42::bigint))
                             ->  Seq Scan on public.int8_tbl b
!                                  Output: b.q1, COALESCE(b.q2, 42::bigint)
                 ->  Seq Scan on public.int8_tbl d
!                      Output: d.q1, COALESCE((COALESCE(b.q2, 42::bigint)), d.q2)
           ->  Hash
                 Output: c.q1, c.q2
                 ->  Seq Scan on public.int8_tbl c
                       Output: c.q1, c.q2
     ->  Result
!          Output: (COALESCE((COALESCE(b.q2, 42::bigint)), d.q2))
  (24 rows)

  -- case that breaks the old ph_may_need optimization
--- 4235,4266 ----
      lateral (select q1, coalesce(ss1.x,q2) as y from int8_tbl d) ss2
    ) on c.q2 = ss2.q1,
    lateral (select ss2.y offset 0) ss3;
!                                                                                      QUERY PLAN
                                                              
!
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Nested Loop
!    Output: c.q1, c.q2, a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)), d.q1, (COALESCE((COALESCE(b.q2,
'42'::bigint)),d.q2)), ((COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))) 
     ->  Hash Right Join
!          Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, '42'::bigint)), (COALESCE((COALESCE(b.q2,
'42'::bigint)),d.q2)) 
           Hash Cond: (d.q1 = c.q2)
           ->  Nested Loop
!                Output: a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, '42'::bigint)), (COALESCE((COALESCE(b.q2,
'42'::bigint)),d.q2)) 
                 ->  Hash Left Join
!                      Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint))
                       Hash Cond: (a.q2 = b.q1)
                       ->  Seq Scan on public.int8_tbl a
                             Output: a.q1, a.q2
                       ->  Hash
!                            Output: b.q1, (COALESCE(b.q2, '42'::bigint))
                             ->  Seq Scan on public.int8_tbl b
!                                  Output: b.q1, COALESCE(b.q2, '42'::bigint)
                 ->  Seq Scan on public.int8_tbl d
!                      Output: d.q1, COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)
           ->  Hash
                 Output: c.q1, c.q2
                 ->  Seq Scan on public.int8_tbl c
                       Output: c.q1, c.q2
     ->  Result
!          Output: (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))
  (24 rows)

  -- case that breaks the old ph_may_need optimization
diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out
index 54525de..d3a98d1 100644
*** a/src/test/regress/expected/rowtypes.out
--- b/src/test/regress/expected/rowtypes.out
*************** ERROR:  cannot compare dissimilar column
*** 284,293 ****
  explain (costs off)
  select * from int8_tbl i8
  where i8 in (row(123,456)::int8_tbl, '(4567890123456789,123)');
!                                                  QUERY PLAN
! -------------------------------------------------------------------------------------------------------------
   Seq Scan on int8_tbl i8
!    Filter: (i8.* = ANY (ARRAY[ROW(123::bigint, 456::bigint)::int8_tbl, '(4567890123456789,123)'::int8_tbl]))
  (2 rows)

  select * from int8_tbl i8
--- 284,293 ----
  explain (costs off)
  select * from int8_tbl i8
  where i8 in (row(123,456)::int8_tbl, '(4567890123456789,123)');
!                                                    QUERY PLAN
! -----------------------------------------------------------------------------------------------------------------
   Seq Scan on int8_tbl i8
!    Filter: (i8.* = ANY (ARRAY[ROW('123'::bigint, '456'::bigint)::int8_tbl, '(4567890123456789,123)'::int8_tbl]))
  (2 rows)

  select * from int8_tbl i8
diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out
index a678e96..016571b 100644
*** a/src/test/regress/expected/union.out
--- b/src/test/regress/expected/union.out
*************** SELECT * FROM
*** 654,666 ****
     UNION
     SELECT 2 AS t, 4 AS x) ss
  WHERE x > 3;
!                                  QUERY PLAN
! ----------------------------------------------------------------------------
   Subquery Scan on ss
     Filter: (ss.x > 3)
     ->  Unique
           ->  Sort
!                Sort Key: (1), (((random() * 3::double precision))::integer)
                 ->  Append
                       ->  Result
                       ->  Result
--- 654,666 ----
     UNION
     SELECT 2 AS t, 4 AS x) ss
  WHERE x > 3;
!                                   QUERY PLAN
! ------------------------------------------------------------------------------
   Subquery Scan on ss
     Filter: (ss.x > 3)
     ->  Unique
           ->  Sort
!                Sort Key: (1), (((random() * '3'::double precision))::integer)
                 ->  Append
                       ->  Result
                       ->  Result
diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out
index 6986f47..a31ec34 100644
*** a/src/test/regress/expected/with.out
--- b/src/test/regress/expected/with.out
*************** SELECT * FROM parent;
*** 2083,2090 ****
  EXPLAIN (VERBOSE, COSTS OFF)
  WITH wcte AS ( INSERT INTO int8_tbl VALUES ( 42, 47 ) RETURNING q2 )
  DELETE FROM a USING wcte WHERE aa = q2;
!                    QUERY PLAN
! ------------------------------------------------
   Delete on public.a
     Delete on public.a
     Delete on public.b
--- 2083,2090 ----
  EXPLAIN (VERBOSE, COSTS OFF)
  WITH wcte AS ( INSERT INTO int8_tbl VALUES ( 42, 47 ) RETURNING q2 )
  DELETE FROM a USING wcte WHERE aa = q2;
!                      QUERY PLAN
! ----------------------------------------------------
   Delete on public.a
     Delete on public.a
     Delete on public.b
*************** DELETE FROM a USING wcte WHERE aa = q2;
*** 2094,2100 ****
       ->  Insert on public.int8_tbl
             Output: int8_tbl.q2
             ->  Result
!                  Output: 42::bigint, 47::bigint
     ->  Nested Loop
           Output: a.ctid, wcte.*
           Join Filter: (a.aa = wcte.q2)
--- 2094,2100 ----
       ->  Insert on public.int8_tbl
             Output: int8_tbl.q2
             ->  Result
!                  Output: '42'::bigint, '47'::bigint
     ->  Nested Loop
           Output: a.ctid, wcte.*
           Join Filter: (a.aa = wcte.q2)

pgsql-bugs by date:

Previous
From: Andrew Gierth
Date:
Subject: Re: Re: BUG #12885: The result of casting a double to an integer depends on the database version
Next
From: Tom Lane
Date:
Subject: Re: pg_get_constraintdef() doesn't always give an equal constraint