6
6
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7
7
* Portions Copyright (c) 1994, Regents of the University of California
8
8
*
9
- * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.314 2004/12/31 22:00:26 pgsql Exp $
9
+ * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.315 2005/02/19 19:33:08 tgl Exp $
10
10
*
11
11
*-------------------------------------------------------------------------
12
12
*/
@@ -506,6 +506,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
506
506
List * * extras_before , List * * extras_after )
507
507
{
508
508
Query * qry = makeNode (Query );
509
+ Query * selectQuery = NULL ;
510
+ bool copy_up_hack = false;
509
511
List * sub_rtable ;
510
512
List * sub_namespace ;
511
513
List * icolumns ;
@@ -561,7 +563,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
561
563
* be able to see.
562
564
*/
563
565
ParseState * sub_pstate = make_parsestate (pstate );
564
- Query * selectQuery ;
565
566
RangeTblEntry * rte ;
566
567
RangeTblRef * rtr ;
567
568
@@ -608,7 +609,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
608
609
Assert (rte == rt_fetch (rtr -> rtindex , pstate -> p_rtable ));
609
610
pstate -> p_joinlist = lappend (pstate -> p_joinlist , rtr );
610
611
611
- /*
612
+ /*----------
612
613
* Generate a targetlist for the INSERT that selects all the
613
614
* non-resjunk columns from the subquery. (We need this to be
614
615
* separate from the subquery's tlist because we may add columns,
@@ -618,8 +619,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
618
619
* are copied up as-is rather than being referenced as subquery
619
620
* outputs. This is to ensure that when we try to coerce them to
620
621
* the target column's datatype, the right things happen (see
621
- * special cases in coerce_type). Otherwise, this fails: INSERT
622
- * INTO foo SELECT 'bar', ... FROM baz
622
+ * special cases in coerce_type). Otherwise, this fails:
623
+ * INSERT INTO foo SELECT 'bar', ... FROM baz
624
+ *----------
623
625
*/
624
626
qry -> targetList = NIL ;
625
627
foreach (tl , selectQuery -> targetList )
@@ -631,9 +633,12 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
631
633
if (resnode -> resjunk )
632
634
continue ;
633
635
if (tle -> expr &&
634
- (IsA (tle -> expr , Const ) || IsA (tle -> expr , Param )) &&
636
+ (IsA (tle -> expr , Const ) || IsA (tle -> expr , Param )) &&
635
637
exprType ((Node * ) tle -> expr ) == UNKNOWNOID )
638
+ {
636
639
expr = tle -> expr ;
640
+ copy_up_hack = true;
641
+ }
637
642
else
638
643
expr = (Expr * ) makeVar (rtr -> rtindex ,
639
644
resnode -> resno ,
@@ -703,6 +708,28 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
703
708
(errcode (ERRCODE_SYNTAX_ERROR ),
704
709
errmsg ("INSERT has more target columns than expressions" )));
705
710
711
+ /*
712
+ * If we copied up any unknown Params (see HACK above) then their
713
+ * resolved types need to be propagated into the Resdom nodes of
714
+ * the sub-INSERT's tlist. One hack begets another :-(
715
+ */
716
+ if (copy_up_hack )
717
+ {
718
+ foreach (tl , selectQuery -> targetList )
719
+ {
720
+ TargetEntry * tle = (TargetEntry * ) lfirst (tl );
721
+ Resdom * resnode = tle -> resdom ;
722
+
723
+ if (resnode -> resjunk )
724
+ continue ;
725
+ if (resnode -> restype == UNKNOWNOID )
726
+ {
727
+ resnode -> restype = exprType ((Node * ) tle -> expr );
728
+ resnode -> restypmod = exprTypmod ((Node * ) tle -> expr );
729
+ }
730
+ }
731
+ }
732
+
706
733
/* done building the range table and jointree */
707
734
qry -> rtable = pstate -> p_rtable ;
708
735
qry -> jointree = makeFromExpr (pstate -> p_joinlist , NULL );
0 commit comments