|
7 | 7 | *
|
8 | 8 | *
|
9 | 9 | * IDENTIFICATION
|
10 |
| - * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.21 1998/08/19 02:02:26 momjian Exp $ |
| 10 | + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.22 1998/08/23 14:43:46 momjian Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
@@ -187,6 +187,154 @@ printf("transformTargetIdent- attrtype_target = %d; type_mod = %d\n", attrtype_t
|
187 | 187 | }/* transformTargetIdent() */
|
188 | 188 |
|
189 | 189 |
|
| 190 | +/* MakeTargetlistExpr() |
| 191 | + * Make a TargetEntry from an expression. |
| 192 | + * arrayRef is a list of transformed A_Indices. |
| 193 | + * |
| 194 | + * For type mismatches between expressions and targets, use the same |
| 195 | + * techniques as for function and operator type coersion. |
| 196 | + * - thomas 1998-05-08 |
| 197 | + * |
| 198 | + * Added resjunk flag and made extern so that it can be use by GROUP/ |
| 199 | + * ORDER BY a function or expersion not in the target_list |
| 200 | + * - daveh@insightdist.com 1998-07-31 |
| 201 | + */ |
| 202 | +TargetEntry* |
| 203 | +MakeTargetlistExpr(ParseState*pstate, |
| 204 | +char*colname, |
| 205 | +Node*expr, |
| 206 | +List*arrayRef, |
| 207 | +int16resjunk) |
| 208 | +{ |
| 209 | +Oidtype_id, |
| 210 | +attrtype; |
| 211 | +int32type_mod, |
| 212 | +attrtypmod; |
| 213 | +intresdomno; |
| 214 | +Relationrd; |
| 215 | +boolattrisset; |
| 216 | +TargetEntry*tent; |
| 217 | +Resdom*resnode; |
| 218 | + |
| 219 | +if (expr==NULL) |
| 220 | +elog(ERROR,"MakeTargetlistExpr: invalid use of NULL expression"); |
| 221 | + |
| 222 | +type_id=exprType(expr); |
| 223 | +if (nodeTag(expr)==T_Var) |
| 224 | +type_mod= ((Var*)expr)->vartypmod; |
| 225 | +else |
| 226 | +type_mod=-1; |
| 227 | + |
| 228 | +/* Processes target columns that will be receiving results */ |
| 229 | +if (pstate->p_is_insert||pstate->p_is_update) |
| 230 | +{ |
| 231 | +/* |
| 232 | + * insert or update query -- insert, update work only on one |
| 233 | + * relation, so multiple occurence of same resdomno is bogus |
| 234 | + */ |
| 235 | +rd=pstate->p_target_relation; |
| 236 | +Assert(rd!=NULL); |
| 237 | +resdomno=attnameAttNum(rd,colname); |
| 238 | +attrisset=attnameIsSet(rd,colname); |
| 239 | +attrtype=attnumTypeId(rd,resdomno); |
| 240 | +if ((arrayRef!=NIL)&& (lfirst(arrayRef)==NIL)) |
| 241 | +attrtype=GetArrayElementType(attrtype); |
| 242 | +attrtypmod=rd->rd_att->attrs[resdomno-1]->atttypmod; |
| 243 | + |
| 244 | +/* Check for InvalidOid since that seems to indicate a NULL constant... */ |
| 245 | +if (type_id!=InvalidOid) |
| 246 | +{ |
| 247 | +/* Mismatch on types? then try to coerce to target... */ |
| 248 | +if (attrtype!=type_id) |
| 249 | +{ |
| 250 | +Oidtypelem; |
| 251 | + |
| 252 | +if (arrayRef&& !(((A_Indices*)lfirst(arrayRef))->lidx)) |
| 253 | +typelem=typeidTypElem(attrtype); |
| 254 | +else |
| 255 | +typelem=attrtype; |
| 256 | + |
| 257 | +expr=CoerceTargetExpr(pstate,expr,type_id,typelem); |
| 258 | + |
| 259 | +if (!HeapTupleIsValid(expr)) |
| 260 | +elog(ERROR,"parser: attribute '%s' is of type '%s'" |
| 261 | +" but expression is of type '%s'" |
| 262 | +"\n\tYou will need to rewrite or cast the expression", |
| 263 | +colname, |
| 264 | +typeidTypeName(attrtype), |
| 265 | +typeidTypeName(type_id)); |
| 266 | +} |
| 267 | + |
| 268 | +#ifdefPARSEDEBUG |
| 269 | +printf("MakeTargetlistExpr: attrtypmod is %d\n", (int4)attrtypmod); |
| 270 | +#endif |
| 271 | + |
| 272 | +/* Apparently going to a fixed-length string? |
| 273 | + * Then explicitly size for storage... |
| 274 | + */ |
| 275 | +if (attrtypmod>0) |
| 276 | +expr=SizeTargetExpr(pstate,expr,attrtype,attrtypmod); |
| 277 | +} |
| 278 | + |
| 279 | +if (arrayRef!=NIL) |
| 280 | +{ |
| 281 | +Expr*target_expr; |
| 282 | +Attr*att=makeNode(Attr); |
| 283 | +List*ar=arrayRef; |
| 284 | +List*upperIndexpr=NIL; |
| 285 | +List*lowerIndexpr=NIL; |
| 286 | + |
| 287 | +att->relname=pstrdup(RelationGetRelationName(rd)->data); |
| 288 | +att->attrs=lcons(makeString(colname),NIL); |
| 289 | +target_expr= (Expr*)ParseNestedFuncOrColumn(pstate,att, |
| 290 | +&pstate->p_last_resno, |
| 291 | +EXPR_COLUMN_FIRST); |
| 292 | +while (ar!=NIL) |
| 293 | +{ |
| 294 | +A_Indices*ind=lfirst(ar); |
| 295 | + |
| 296 | +if (lowerIndexpr|| (!upperIndexpr&&ind->lidx)) |
| 297 | +{ |
| 298 | + |
| 299 | +/* |
| 300 | + * XXX assume all lowerIndexpr is non-null in this |
| 301 | + * case |
| 302 | + */ |
| 303 | +lowerIndexpr=lappend(lowerIndexpr,ind->lidx); |
| 304 | +} |
| 305 | +upperIndexpr=lappend(upperIndexpr,ind->uidx); |
| 306 | +ar=lnext(ar); |
| 307 | +} |
| 308 | + |
| 309 | +expr= (Node*)make_array_set(target_expr, |
| 310 | +upperIndexpr, |
| 311 | +lowerIndexpr, |
| 312 | + (Expr*)expr); |
| 313 | +attrtype=attnumTypeId(rd,resdomno); |
| 314 | +attrtypmod=get_atttypmod(RelationGetRelid(rd),resdomno); |
| 315 | +} |
| 316 | +} |
| 317 | +else |
| 318 | +{ |
| 319 | +resdomno=pstate->p_last_resno++; |
| 320 | +attrtype=type_id; |
| 321 | +attrtypmod=type_mod; |
| 322 | +} |
| 323 | + |
| 324 | +resnode=makeResdom((AttrNumber)resdomno, |
| 325 | + (Oid)attrtype, |
| 326 | +attrtypmod, |
| 327 | +colname, |
| 328 | + (Index)0, |
| 329 | + (Oid)0, |
| 330 | +resjunk); |
| 331 | + |
| 332 | +tent=makeTargetEntry(resnode,expr); |
| 333 | + |
| 334 | +returntent; |
| 335 | +}/* MakeTargetlistExpr() */ |
| 336 | + |
| 337 | + |
190 | 338 | /* transformTargetList()
|
191 | 339 | * Turns a list of ResTarget's into a list of TargetEntry's.
|
192 | 340 | */
|
@@ -299,7 +447,6 @@ printf("transformTargetList: decode T_Expr\n");
|
299 | 447 | /* this is not an array assignment */
|
300 | 448 | if (colname==NULL)
|
301 | 449 | {
|
302 |
| - |
303 | 450 | /*
|
304 | 451 | * if you're wondering why this is here, look
|
305 | 452 | * at the yacc grammar for why a name can be
|
@@ -559,154 +706,6 @@ printf("SizeTargetExpr: no conversion function for sizing\n");
|
559 | 706 | }/* SizeTargetExpr() */
|
560 | 707 |
|
561 | 708 |
|
562 |
| -/* MakeTargetlistExpr() |
563 |
| - * Make a TargetEntry from an expression. |
564 |
| - * arrayRef is a list of transformed A_Indices. |
565 |
| - * |
566 |
| - * For type mismatches between expressions and targets, use the same |
567 |
| - * techniques as for function and operator type coersion. |
568 |
| - * - thomas 1998-05-08 |
569 |
| - * |
570 |
| - * Added resjunk flag and made extern so that it can be use by GROUP/ |
571 |
| - * ORDER BY a function or expersion not in the target_list |
572 |
| - * - daveh@insightdist.com 1998-07-31 |
573 |
| - */ |
574 |
| -TargetEntry* |
575 |
| -MakeTargetlistExpr(ParseState*pstate, |
576 |
| -char*colname, |
577 |
| -Node*expr, |
578 |
| -List*arrayRef, |
579 |
| -int16resjunk) |
580 |
| -{ |
581 |
| -Oidtype_id, |
582 |
| -attrtype; |
583 |
| -int32type_mod, |
584 |
| -attrtypmod; |
585 |
| -intresdomno; |
586 |
| -Relationrd; |
587 |
| -boolattrisset; |
588 |
| -TargetEntry*tent; |
589 |
| -Resdom*resnode; |
590 |
| - |
591 |
| -if (expr==NULL) |
592 |
| -elog(ERROR,"MakeTargetlistExpr: invalid use of NULL expression"); |
593 |
| - |
594 |
| -type_id=exprType(expr); |
595 |
| -if (nodeTag(expr)==T_Var) |
596 |
| -type_mod= ((Var*)expr)->vartypmod; |
597 |
| -else |
598 |
| -type_mod=-1; |
599 |
| - |
600 |
| -/* Processes target columns that will be receiving results */ |
601 |
| -if (pstate->p_is_insert||pstate->p_is_update) |
602 |
| -{ |
603 |
| -/* |
604 |
| - * insert or update query -- insert, update work only on one |
605 |
| - * relation, so multiple occurence of same resdomno is bogus |
606 |
| - */ |
607 |
| -rd=pstate->p_target_relation; |
608 |
| -Assert(rd!=NULL); |
609 |
| -resdomno=attnameAttNum(rd,colname); |
610 |
| -attrisset=attnameIsSet(rd,colname); |
611 |
| -attrtype=attnumTypeId(rd,resdomno); |
612 |
| -if ((arrayRef!=NIL)&& (lfirst(arrayRef)==NIL)) |
613 |
| -attrtype=GetArrayElementType(attrtype); |
614 |
| -attrtypmod=rd->rd_att->attrs[resdomno-1]->atttypmod; |
615 |
| - |
616 |
| -/* Check for InvalidOid since that seems to indicate a NULL constant... */ |
617 |
| -if (type_id!=InvalidOid) |
618 |
| -{ |
619 |
| -/* Mismatch on types? then try to coerce to target... */ |
620 |
| -if (attrtype!=type_id) |
621 |
| -{ |
622 |
| -Oidtypelem; |
623 |
| - |
624 |
| -if (arrayRef&& !(((A_Indices*)lfirst(arrayRef))->lidx)) |
625 |
| -typelem=typeidTypElem(attrtype); |
626 |
| -else |
627 |
| -typelem=attrtype; |
628 |
| - |
629 |
| -expr=CoerceTargetExpr(pstate,expr,type_id,typelem); |
630 |
| - |
631 |
| -if (!HeapTupleIsValid(expr)) |
632 |
| -elog(ERROR,"parser: attribute '%s' is of type '%s'" |
633 |
| -" but expression is of type '%s'" |
634 |
| -"\n\tYou will need to rewrite or cast the expression", |
635 |
| -colname, |
636 |
| -typeidTypeName(attrtype), |
637 |
| -typeidTypeName(type_id)); |
638 |
| -} |
639 |
| - |
640 |
| -#ifdefPARSEDEBUG |
641 |
| -printf("MakeTargetlistExpr: attrtypmod is %d\n", (int4)attrtypmod); |
642 |
| -#endif |
643 |
| - |
644 |
| -/* Apparently going to a fixed-length string? |
645 |
| - * Then explicitly size for storage... |
646 |
| - */ |
647 |
| -if (attrtypmod>0) |
648 |
| -expr=SizeTargetExpr(pstate,expr,attrtype,attrtypmod); |
649 |
| -} |
650 |
| - |
651 |
| -if (arrayRef!=NIL) |
652 |
| -{ |
653 |
| -Expr*target_expr; |
654 |
| -Attr*att=makeNode(Attr); |
655 |
| -List*ar=arrayRef; |
656 |
| -List*upperIndexpr=NIL; |
657 |
| -List*lowerIndexpr=NIL; |
658 |
| - |
659 |
| -att->relname=pstrdup(RelationGetRelationName(rd)->data); |
660 |
| -att->attrs=lcons(makeString(colname),NIL); |
661 |
| -target_expr= (Expr*)ParseNestedFuncOrColumn(pstate,att, |
662 |
| -&pstate->p_last_resno, |
663 |
| -EXPR_COLUMN_FIRST); |
664 |
| -while (ar!=NIL) |
665 |
| -{ |
666 |
| -A_Indices*ind=lfirst(ar); |
667 |
| - |
668 |
| -if (lowerIndexpr|| (!upperIndexpr&&ind->lidx)) |
669 |
| -{ |
670 |
| - |
671 |
| -/* |
672 |
| - * XXX assume all lowerIndexpr is non-null in this |
673 |
| - * case |
674 |
| - */ |
675 |
| -lowerIndexpr=lappend(lowerIndexpr,ind->lidx); |
676 |
| -} |
677 |
| -upperIndexpr=lappend(upperIndexpr,ind->uidx); |
678 |
| -ar=lnext(ar); |
679 |
| -} |
680 |
| - |
681 |
| -expr= (Node*)make_array_set(target_expr, |
682 |
| -upperIndexpr, |
683 |
| -lowerIndexpr, |
684 |
| - (Expr*)expr); |
685 |
| -attrtype=attnumTypeId(rd,resdomno); |
686 |
| -attrtypmod=get_atttypmod(RelationGetRelid(rd),resdomno); |
687 |
| -} |
688 |
| -} |
689 |
| -else |
690 |
| -{ |
691 |
| -resdomno=pstate->p_last_resno++; |
692 |
| -attrtype=type_id; |
693 |
| -attrtypmod=type_mod; |
694 |
| -} |
695 |
| - |
696 |
| -resnode=makeResdom((AttrNumber)resdomno, |
697 |
| - (Oid)attrtype, |
698 |
| -attrtypmod, |
699 |
| -colname, |
700 |
| - (Index)0, |
701 |
| - (Oid)0, |
702 |
| -resjunk); |
703 |
| - |
704 |
| -tent=makeTargetEntry(resnode,expr); |
705 |
| - |
706 |
| -returntent; |
707 |
| -}/* MakeTargetlistExpr() */ |
708 |
| - |
709 |
| - |
710 | 709 | /*
|
711 | 710 | * makeTargetNames -
|
712 | 711 | * generate a list of column names if not supplied or
|
|