From 9cad9febb172b09ff8c2366a4e19469926304f0d Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Sun, 23 Aug 1998 14:43:46 +0000 Subject: [PATCH] cleanup --- src/backend/parser/README | 2 +- src/backend/parser/parse_target.c | 299 +++++++++++++++--------------- 2 files changed, 150 insertions(+), 151 deletions(-) diff --git a/src/backend/parser/README b/src/backend/parser/README index b67e1909d9..effa9008fa 100644 --- a/src/backend/parser/README +++ b/src/backend/parser/README @@ -9,11 +9,11 @@ keywords.c turn keywords into specific tokens gram.y parse the tokens and fill query-type-specific structures analyze.c handle post-parse processing for each query type parse_clause.c handle clauses like WHERE, ORDER BY, GROUP BY, ... +parse_coerce.c used for coercing expressions of different types parse_expr.c handle expressions like col, col + 3, x = 3 or x = 4 parse_oper.c handle operations in expressions parse_agg.c handle aggregates, like SUM(col1), AVG(col2), ... parse_func.c handle functions, table.column and column identifiers - parse_node.c create nodes for various structures parse_target.c handle the result list of the query parse_relation.c support routines for tables and column handling diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index a71df49279..b54e1b6786 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.21 1998/08/19 02:02:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.22 1998/08/23 14:43:46 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -187,6 +187,154 @@ printf("transformTargetIdent- attrtype_target = %d; type_mod = %d\n", attrtype_t } /* transformTargetIdent() */ +/* MakeTargetlistExpr() + * Make a TargetEntry from an expression. + * arrayRef is a list of transformed A_Indices. + * + * For type mismatches between expressions and targets, use the same + * techniques as for function and operator type coersion. + * - thomas 1998-05-08 + * + * Added resjunk flag and made extern so that it can be use by GROUP/ + * ORDER BY a function or expersion not in the target_list + * - daveh@insightdist.com 1998-07-31 + */ +TargetEntry * +MakeTargetlistExpr(ParseState *pstate, + char *colname, + Node *expr, + List *arrayRef, + int16 resjunk) +{ + Oid type_id, + attrtype; + int32 type_mod, + attrtypmod; + int resdomno; + Relation rd; + bool attrisset; + TargetEntry *tent; + Resdom *resnode; + + if (expr == NULL) + elog(ERROR, "MakeTargetlistExpr: invalid use of NULL expression"); + + type_id = exprType(expr); + if (nodeTag(expr) == T_Var) + type_mod = ((Var *) expr)->vartypmod; + else + type_mod = -1; + + /* Processes target columns that will be receiving results */ + if (pstate->p_is_insert || pstate->p_is_update) + { + /* + * insert or update query -- insert, update work only on one + * relation, so multiple occurence of same resdomno is bogus + */ + rd = pstate->p_target_relation; + Assert(rd != NULL); + resdomno = attnameAttNum(rd, colname); + attrisset = attnameIsSet(rd, colname); + attrtype = attnumTypeId(rd, resdomno); + if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL)) + attrtype = GetArrayElementType(attrtype); + attrtypmod = rd->rd_att->attrs[resdomno - 1]->atttypmod; + + /* Check for InvalidOid since that seems to indicate a NULL constant... */ + if (type_id != InvalidOid) + { + /* Mismatch on types? then try to coerce to target... */ + if (attrtype != type_id) + { + Oid typelem; + + if (arrayRef && !(((A_Indices *) lfirst(arrayRef))->lidx)) + typelem = typeidTypElem(attrtype); + else + typelem = attrtype; + + expr = CoerceTargetExpr(pstate, expr, type_id, typelem); + + if (!HeapTupleIsValid(expr)) + elog(ERROR, "parser: attribute '%s' is of type '%s'" + " but expression is of type '%s'" + "\n\tYou will need to rewrite or cast the expression", + colname, + typeidTypeName(attrtype), + typeidTypeName(type_id)); + } + +#ifdef PARSEDEBUG +printf("MakeTargetlistExpr: attrtypmod is %d\n", (int4) attrtypmod); +#endif + + /* Apparently going to a fixed-length string? + * Then explicitly size for storage... + */ + if (attrtypmod > 0) + expr = SizeTargetExpr(pstate, expr, attrtype, attrtypmod); + } + + if (arrayRef != NIL) + { + Expr *target_expr; + Attr *att = makeNode(Attr); + List *ar = arrayRef; + List *upperIndexpr = NIL; + List *lowerIndexpr = NIL; + + att->relname = pstrdup(RelationGetRelationName(rd)->data); + att->attrs = lcons(makeString(colname), NIL); + target_expr = (Expr *) ParseNestedFuncOrColumn(pstate, att, + &pstate->p_last_resno, + EXPR_COLUMN_FIRST); + while (ar != NIL) + { + A_Indices *ind = lfirst(ar); + + if (lowerIndexpr || (!upperIndexpr && ind->lidx)) + { + + /* + * XXX assume all lowerIndexpr is non-null in this + * case + */ + lowerIndexpr = lappend(lowerIndexpr, ind->lidx); + } + upperIndexpr = lappend(upperIndexpr, ind->uidx); + ar = lnext(ar); + } + + expr = (Node *) make_array_set(target_expr, + upperIndexpr, + lowerIndexpr, + (Expr *) expr); + attrtype = attnumTypeId(rd, resdomno); + attrtypmod = get_atttypmod(RelationGetRelid(rd), resdomno); + } + } + else + { + resdomno = pstate->p_last_resno++; + attrtype = type_id; + attrtypmod = type_mod; + } + + resnode = makeResdom((AttrNumber) resdomno, + (Oid) attrtype, + attrtypmod, + colname, + (Index) 0, + (Oid) 0, + resjunk); + + tent = makeTargetEntry(resnode, expr); + + return tent; +} /* MakeTargetlistExpr() */ + + /* transformTargetList() * Turns a list of ResTarget's into a list of TargetEntry's. */ @@ -299,7 +447,6 @@ printf("transformTargetList: decode T_Expr\n"); /* this is not an array assignment */ if (colname == NULL) { - /* * if you're wondering why this is here, look * at the yacc grammar for why a name can be @@ -559,154 +706,6 @@ printf("SizeTargetExpr: no conversion function for sizing\n"); } /* SizeTargetExpr() */ -/* MakeTargetlistExpr() - * Make a TargetEntry from an expression. - * arrayRef is a list of transformed A_Indices. - * - * For type mismatches between expressions and targets, use the same - * techniques as for function and operator type coersion. - * - thomas 1998-05-08 - * - * Added resjunk flag and made extern so that it can be use by GROUP/ - * ORDER BY a function or expersion not in the target_list - * - daveh@insightdist.com 1998-07-31 - */ -TargetEntry * -MakeTargetlistExpr(ParseState *pstate, - char *colname, - Node *expr, - List *arrayRef, - int16 resjunk) -{ - Oid type_id, - attrtype; - int32 type_mod, - attrtypmod; - int resdomno; - Relation rd; - bool attrisset; - TargetEntry *tent; - Resdom *resnode; - - if (expr == NULL) - elog(ERROR, "MakeTargetlistExpr: invalid use of NULL expression"); - - type_id = exprType(expr); - if (nodeTag(expr) == T_Var) - type_mod = ((Var *) expr)->vartypmod; - else - type_mod = -1; - - /* Processes target columns that will be receiving results */ - if (pstate->p_is_insert || pstate->p_is_update) - { - /* - * insert or update query -- insert, update work only on one - * relation, so multiple occurence of same resdomno is bogus - */ - rd = pstate->p_target_relation; - Assert(rd != NULL); - resdomno = attnameAttNum(rd, colname); - attrisset = attnameIsSet(rd, colname); - attrtype = attnumTypeId(rd, resdomno); - if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL)) - attrtype = GetArrayElementType(attrtype); - attrtypmod = rd->rd_att->attrs[resdomno - 1]->atttypmod; - - /* Check for InvalidOid since that seems to indicate a NULL constant... */ - if (type_id != InvalidOid) - { - /* Mismatch on types? then try to coerce to target... */ - if (attrtype != type_id) - { - Oid typelem; - - if (arrayRef && !(((A_Indices *) lfirst(arrayRef))->lidx)) - typelem = typeidTypElem(attrtype); - else - typelem = attrtype; - - expr = CoerceTargetExpr(pstate, expr, type_id, typelem); - - if (!HeapTupleIsValid(expr)) - elog(ERROR, "parser: attribute '%s' is of type '%s'" - " but expression is of type '%s'" - "\n\tYou will need to rewrite or cast the expression", - colname, - typeidTypeName(attrtype), - typeidTypeName(type_id)); - } - -#ifdef PARSEDEBUG -printf("MakeTargetlistExpr: attrtypmod is %d\n", (int4) attrtypmod); -#endif - - /* Apparently going to a fixed-length string? - * Then explicitly size for storage... - */ - if (attrtypmod > 0) - expr = SizeTargetExpr(pstate, expr, attrtype, attrtypmod); - } - - if (arrayRef != NIL) - { - Expr *target_expr; - Attr *att = makeNode(Attr); - List *ar = arrayRef; - List *upperIndexpr = NIL; - List *lowerIndexpr = NIL; - - att->relname = pstrdup(RelationGetRelationName(rd)->data); - att->attrs = lcons(makeString(colname), NIL); - target_expr = (Expr *) ParseNestedFuncOrColumn(pstate, att, - &pstate->p_last_resno, - EXPR_COLUMN_FIRST); - while (ar != NIL) - { - A_Indices *ind = lfirst(ar); - - if (lowerIndexpr || (!upperIndexpr && ind->lidx)) - { - - /* - * XXX assume all lowerIndexpr is non-null in this - * case - */ - lowerIndexpr = lappend(lowerIndexpr, ind->lidx); - } - upperIndexpr = lappend(upperIndexpr, ind->uidx); - ar = lnext(ar); - } - - expr = (Node *) make_array_set(target_expr, - upperIndexpr, - lowerIndexpr, - (Expr *) expr); - attrtype = attnumTypeId(rd, resdomno); - attrtypmod = get_atttypmod(RelationGetRelid(rd), resdomno); - } - } - else - { - resdomno = pstate->p_last_resno++; - attrtype = type_id; - attrtypmod = type_mod; - } - - resnode = makeResdom((AttrNumber) resdomno, - (Oid) attrtype, - attrtypmod, - colname, - (Index) 0, - (Oid) 0, - resjunk); - - tent = makeTargetEntry(resnode, expr); - - return tent; -} /* MakeTargetlistExpr() */ - - /* * makeTargetNames - * generate a list of column names if not supplied or