|
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 | + int16 resjunk) |
| 208 | +{ |
| 209 | + Oid type_id, |
| 210 | + attrtype; |
| 211 | + int32 type_mod, |
| 212 | + attrtypmod; |
| 213 | + int resdomno; |
| 214 | + Relation rd; |
| 215 | + bool attrisset; |
| 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 | + Oid typelem; |
| 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 | +#ifdef PARSEDEBUG |
| 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 | + return tent; |
| 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 |
| - int16 resjunk) |
580 |
| -{ |
581 |
| - Oid type_id, |
582 |
| - attrtype; |
583 |
| - int32 type_mod, |
584 |
| - attrtypmod; |
585 |
| - int resdomno; |
586 |
| - Relation rd; |
587 |
| - bool attrisset; |
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 |
| - Oid typelem; |
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 |
| -#ifdef PARSEDEBUG |
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 |
| - return tent; |
707 |
| -} /* MakeTargetlistExpr() */ |
708 |
| - |
709 |
| - |
710 | 709 | /*
|
711 | 710 | * makeTargetNames -
|
712 | 711 | * generate a list of column names if not supplied or
|
|
0 commit comments