This commit is contained in:
Bruce Momjian 1998-08-23 14:43:46 +00:00
parent 985f4ab98a
commit 9cad9febb1
2 changed files with 150 additions and 151 deletions

View File

@ -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

View File

@ -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