If the alternatives for a CASE construct all have the same typmod,
authorTom Lane
Mon, 12 Nov 2001 20:05:24 +0000 (20:05 +0000)
committerTom Lane
Mon, 12 Nov 2001 20:05:24 +0000 (20:05 +0000)
use that typmod not -1 as the typmod of the CASE result.
Part of response to bug#513.

src/backend/parser/parse_expr.c

index 333333b0408d520e294be91634be75ffa801c343..339999c0c6356de510073b896e81697031b82357 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.104 2001/10/25 05:49:39 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.105 2001/11/12 20:05:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -806,6 +806,37 @@ exprTypmod(Node *expr)
        case T_RelabelType:
            return ((RelabelType *) expr)->resulttypmod;
            break;
+       case T_CaseExpr:
+           {
+               /*
+                * If all the alternatives agree on type/typmod, return
+                * that typmod, else use -1
+                */
+               CaseExpr   *cexpr = (CaseExpr *) expr;
+               Oid         casetype = cexpr->casetype;
+               int32       typmod;
+               List       *arg;
+
+               if (!cexpr->defresult)
+                   return -1;
+               if (exprType(cexpr->defresult) != casetype)
+                   return -1;
+               typmod = exprTypmod(cexpr->defresult);
+               if (typmod < 0)
+                   return -1;  /* no point in trying harder */
+               foreach(arg, cexpr->args)
+               {
+                   CaseWhen   *w = (CaseWhen *) lfirst(arg);
+
+                   Assert(IsA(w, CaseWhen));
+                   if (exprType(w->result) != casetype)
+                       return -1;
+                   if (exprTypmod(w->result) != typmod)
+                       return -1;
+               }
+               return typmod;
+           }
+           break;
        default:
            break;
    }