cleanup
This commit is contained in:
parent
985f4ab98a
commit
9cad9febb1
|
@ -9,11 +9,11 @@ keywords.c turn keywords into specific tokens
|
||||||
gram.y parse the tokens and fill query-type-specific structures
|
gram.y parse the tokens and fill query-type-specific structures
|
||||||
analyze.c handle post-parse processing for each query type
|
analyze.c handle post-parse processing for each query type
|
||||||
parse_clause.c handle clauses like WHERE, ORDER BY, GROUP BY, ...
|
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_expr.c handle expressions like col, col + 3, x = 3 or x = 4
|
||||||
parse_oper.c handle operations in expressions
|
parse_oper.c handle operations in expressions
|
||||||
parse_agg.c handle aggregates, like SUM(col1), AVG(col2), ...
|
parse_agg.c handle aggregates, like SUM(col1), AVG(col2), ...
|
||||||
parse_func.c handle functions, table.column and column identifiers
|
parse_func.c handle functions, table.column and column identifiers
|
||||||
|
|
||||||
parse_node.c create nodes for various structures
|
parse_node.c create nodes for various structures
|
||||||
parse_target.c handle the result list of the query
|
parse_target.c handle the result list of the query
|
||||||
parse_relation.c support routines for tables and column handling
|
parse_relation.c support routines for tables and column handling
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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() */
|
} /* 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()
|
/* transformTargetList()
|
||||||
* Turns a list of ResTarget's into a list of TargetEntry's.
|
* 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 */
|
/* this is not an array assignment */
|
||||||
if (colname == NULL)
|
if (colname == NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if you're wondering why this is here, look
|
* if you're wondering why this is here, look
|
||||||
* at the yacc grammar for why a name can be
|
* at the yacc grammar for why a name can be
|
||||||
|
@ -559,154 +706,6 @@ printf("SizeTargetExpr: no conversion function for sizing\n");
|
||||||
} /* SizeTargetExpr() */
|
} /* 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 -
|
* makeTargetNames -
|
||||||
* generate a list of column names if not supplied or
|
* generate a list of column names if not supplied or
|
||||||
|
|
Loading…
Reference in New Issue