Abhijit Menon-Sen <[EMAIL PROTECTED]> writes:
> Summary: I can crash 7.4-CVS and 8.0/HEAD by sending what appears to be
> a valid query.

Good catch.  I've applied the attached patch (this is against 8.0/CVS
tip but applies with some fuzz to 7.4).

                        regards, tom lane

*** src/backend/parser/analyze.c.orig   Fri Dec 31 17:45:54 2004
--- src/backend/parser/analyze.c        Sat Feb 19 13:57:51 2005
***************
*** 506,511 ****
--- 506,513 ----
                                        List **extras_before, List 
**extras_after)
  {
        Query      *qry = makeNode(Query);
+       Query      *selectQuery = NULL;
+       bool            copy_up_hack = false;
        List       *sub_rtable;
        List       *sub_namespace;
        List       *icolumns;
***************
*** 561,567 ****
                 * be able to see.
                 */
                ParseState *sub_pstate = make_parsestate(pstate);
-               Query      *selectQuery;
                RangeTblEntry *rte;
                RangeTblRef *rtr;
  
--- 563,568 ----
***************
*** 608,614 ****
                Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
                pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
  
!               /*
                 * Generate a targetlist for the INSERT that selects all the
                 * non-resjunk columns from the subquery.  (We need this to be
                 * separate from the subquery's tlist because we may add 
columns,
--- 609,615 ----
                Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
                pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
  
!               /*----------
                 * Generate a targetlist for the INSERT that selects all the
                 * non-resjunk columns from the subquery.  (We need this to be
                 * separate from the subquery's tlist because we may add 
columns,
***************
*** 618,625 ****
                 * are copied up as-is rather than being referenced as subquery
                 * outputs.  This is to ensure that when we try to coerce them 
to
                 * the target column's datatype, the right things happen (see
!                * special cases in coerce_type).  Otherwise, this fails: INSERT
!                * INTO foo SELECT 'bar', ... FROM baz
                 */
                qry->targetList = NIL;
                foreach(tl, selectQuery->targetList)
--- 619,627 ----
                 * are copied up as-is rather than being referenced as subquery
                 * outputs.  This is to ensure that when we try to coerce them 
to
                 * the target column's datatype, the right things happen (see
!                * special cases in coerce_type).  Otherwise, this fails:
!                *              INSERT INTO foo SELECT 'bar', ... FROM baz
!                *----------
                 */
                qry->targetList = NIL;
                foreach(tl, selectQuery->targetList)
***************
*** 631,639 ****
                        if (resnode->resjunk)
                                continue;
                        if (tle->expr &&
!                               (IsA(tle->expr, Const) ||IsA(tle->expr, Param)) 
&&
                                exprType((Node *) tle->expr) == UNKNOWNOID)
                                expr = tle->expr;
                        else
                                expr = (Expr *) makeVar(rtr->rtindex,
                                                                                
resnode->resno,
--- 633,644 ----
                        if (resnode->resjunk)
                                continue;
                        if (tle->expr &&
!                               (IsA(tle->expr, Const) || IsA(tle->expr, 
Param)) &&
                                exprType((Node *) tle->expr) == UNKNOWNOID)
+                       {
                                expr = tle->expr;
+                               copy_up_hack = true;
+                       }
                        else
                                expr = (Expr *) makeVar(rtr->rtindex,
                                                                                
resnode->resno,
***************
*** 702,707 ****
--- 707,734 ----
                ereport(ERROR,
                                (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("INSERT has more target columns than 
expressions")));
+ 
+       /*
+        * If we copied up any unknown Params (see HACK above) then their
+        * resolved types need to be propagated into the Resdom nodes of
+        * the sub-INSERT's tlist.  One hack begets another :-(
+        */
+       if (copy_up_hack)
+       {
+               foreach(tl, selectQuery->targetList)
+               {
+                       TargetEntry *tle = (TargetEntry *) lfirst(tl);
+                       Resdom     *resnode = tle->resdom;
+ 
+                       if (resnode->resjunk)
+                               continue;
+                       if (resnode->restype == UNKNOWNOID)
+                       {
+                               resnode->restype = exprType((Node *) tle->expr);
+                               resnode->restypmod = exprTypmod((Node *) 
tle->expr);
+                       }
+               }
+       }
  
        /* done building the range table and jointree */
        qry->rtable = pstate->p_rtable;

---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
      joining column's datatypes do not match

Reply via email to