aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/analyze.c4
-rw-r--r--src/backend/parser/parse_expr.c14
-rw-r--r--src/backend/parser/parse_func.c226
-rw-r--r--src/backend/parser/parse_node.c6
-rw-r--r--src/backend/parser/parse_relation.c4
-rw-r--r--src/backend/parser/parse_target.c4
6 files changed, 79 insertions, 179 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 5824c300d7c..09f90fe3bc3 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: analyze.c,v 1.152 2000/08/03 16:35:08 tgl Exp $
+ * $Id: analyze.c,v 1.153 2000/08/08 15:42:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -470,7 +470,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
thisatt->atttypid,
thisatt->atttypmod,
pstrdup(NameStr(thisatt->attname)),
- 0, 0, false),
+ false),
stringToNode(defval[ndef].adbin));
qry->targetList = lappend(qry->targetList, te);
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 8c3e64d6d86..7976f5e7795 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.81 2000/06/15 03:32:20 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.82 2000/08/08 15:42:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -133,7 +133,6 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
param->paramid = (AttrNumber) paramno;
param->paramname = "<unnamed>";
param->paramtype = toid;
- param->param_tlist = NIL;
result = transformIndirection(pstate, (Node *) param,
pno->indirection);
/* cope with typecast applied to param */
@@ -381,9 +380,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
newop = makeOper(oprid(optup), /* opno */
InvalidOid, /* opid */
- opform->oprresult,
- 0,
- NULL);
+ opform->oprresult);
sublink->oper = lappend(sublink->oper, newop);
}
if (left_list != NIL)
@@ -579,6 +576,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
case T_Param:
case T_Aggref:
case T_ArrayRef:
+ case T_FieldSelect:
case T_RelabelType:
{
result = (Node *) expr;
@@ -690,6 +688,9 @@ exprType(Node *expr)
case T_Param:
type = ((Param *) expr)->paramtype;
break;
+ case T_FieldSelect:
+ type = ((FieldSelect *) expr)->resulttype;
+ break;
case T_RelabelType:
type = ((RelabelType *) expr)->resulttype;
break;
@@ -773,6 +774,9 @@ exprTypmod(Node *expr)
return coercedTypmod;
}
break;
+ case T_FieldSelect:
+ return ((FieldSelect *) expr)->resulttypmod;
+ break;
case T_RelabelType:
return ((RelabelType *) expr)->resulttypmod;
break;
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index d1a5e44f873..44a750c166e 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.86 2000/08/03 19:19:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.87 2000/08/08 15:42:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -59,7 +59,7 @@ static int match_argtypes(int nargs,
Oid *input_typeids,
CandidateList function_typeids,
CandidateList *candidates);
-static List *setup_tlist(char *attname, Oid relid);
+static FieldSelect *setup_field_select(Node *input, char *attname, Oid relid);
static Oid *func_select_candidate(int nargs, Oid *input_typeids,
CandidateList candidates);
static int agg_get_candidates(char *aggname, Oid typeId, CandidateList *candidates);
@@ -394,10 +394,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
argrelid = typeidTypeRelid(toid);
/*
- * A projection contains either an attribute name or "*".
+ * A projection must match an attribute name of the rel.
*/
- if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
- && strcmp(funcname, "*"))
+ if (get_attnum(argrelid, funcname) == InvalidAttrNumber)
elog(ERROR, "Functions on sets are not yet supported");
}
@@ -670,43 +669,12 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
funcnode = makeNode(Func);
funcnode->funcid = funcid;
funcnode->functype = rettype;
- funcnode->funcisindex = false;
- funcnode->funcsize = 0;
funcnode->func_fcache = NULL;
- funcnode->func_tlist = NIL;
- funcnode->func_planlist = NIL;
- /* perform the necessary typecasting */
+ /* perform the necessary typecasting of arguments */
make_arguments(pstate, nargs, fargs, oid_array, true_oid_array);
/*
- * for functions returning base types, we want to project out the
- * return value. set up a target list to do that. the executor will
- * ignore these for c functions, and do the right thing for postquel
- * functions.
- */
-
- if (typeidTypeRelid(rettype) == InvalidOid)
- funcnode->func_tlist = setup_base_tlist(rettype);
-
- /*
- * For sets, we want to make a targetlist to project out this
- * attribute of the set tuples.
- */
- if (attisset)
- {
- if (!strcmp(funcname, "*"))
- funcnode->func_tlist = expandAll(pstate, relname,
- makeAttr(refname, NULL),
- curr_resno);
- else
- {
- funcnode->func_tlist = setup_tlist(funcname, argrelid);
- rettype = get_atttype(argrelid, get_attnum(argrelid, funcname));
- }
- }
-
- /*
* Special checks to disallow sequence functions with side-effects
* in WHERE clauses. This is pretty much of a hack; why disallow these
* when we have no way to check for side-effects of user-defined fns?
@@ -724,6 +692,18 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
retval = (Node *) expr;
/*
+ * For sets, we want to project out the desired attribute of the tuples.
+ */
+ if (attisset)
+ {
+ FieldSelect *fselect;
+
+ fselect = setup_field_select(retval, funcname, argrelid);
+ rettype = fselect->resulttype;
+ retval = (Node *) fselect;
+ }
+
+ /*
* if the function returns a set of values, then we need to iterate
* over all the returned values in the executor, so we stick an iter
* node here. if it returns a singleton, then we don't need the iter
@@ -1524,66 +1504,30 @@ make_arguments(ParseState *pstate,
}
/*
- ** setup_tlist
- ** Build a tlist that says which attribute to project to.
- ** This routine is called by ParseFuncOrColumn() to set up a target list
- ** on a tuple parameter or return value. Due to a bug in 4.0,
- ** it's not possible to refer to system attributes in this case.
+ ** setup_field_select
+ ** Build a FieldSelect node that says which attribute to project to.
+ ** This routine is called by ParseFuncOrColumn() when we have found
+ ** a projection on a function result or parameter.
*/
-static List *
-setup_tlist(char *attname, Oid relid)
+static FieldSelect *
+setup_field_select(Node *input, char *attname, Oid relid)
{
- TargetEntry *tle;
- Resdom *resnode;
- Var *varnode;
- Oid typeid;
- int32 type_mod;
- int attno;
+ FieldSelect *fselect = makeNode(FieldSelect);
+ AttrNumber attno;
attno = get_attnum(relid, attname);
+
+ /* XXX Is there still a reason for this restriction? */
if (attno < 0)
elog(ERROR, "Cannot reference attribute '%s'"
" of tuple params/return values for functions", attname);
- typeid = get_atttype(relid, attno);
- type_mod = get_atttypmod(relid, attno);
-
- resnode = makeResdom(1,
- typeid,
- type_mod,
- get_attname(relid, attno),
- 0,
- InvalidOid,
- false);
- varnode = makeVar(-1, attno, typeid, type_mod, 0);
+ fselect->arg = input;
+ fselect->fieldnum = attno;
+ fselect->resulttype = get_atttype(relid, attno);
+ fselect->resulttypmod = get_atttypmod(relid, attno);
- tle = makeTargetEntry(resnode, (Node *) varnode);
- return lcons(tle, NIL);
-}
-
-/*
- ** setup_base_tlist
- ** Build a tlist that extracts a base type from the tuple
- ** returned by the executor.
- */
-List *
-setup_base_tlist(Oid typeid)
-{
- TargetEntry *tle;
- Resdom *resnode;
- Var *varnode;
-
- resnode = makeResdom(1,
- typeid,
- -1,
- "<noname>",
- 0,
- InvalidOid,
- false);
- varnode = makeVar(-1, 1, typeid, -1, 0);
- tle = makeTargetEntry(resnode, (Node *) varnode);
-
- return lcons(tle, NIL);
+ return fselect;
}
/*
@@ -1599,51 +1543,32 @@ ParseComplexProjection(ParseState *pstate,
{
Oid argtype;
Oid argrelid;
- Relation rd;
- Oid relid;
- int attnum;
+ FieldSelect *fselect;
switch (nodeTag(first_arg))
{
case T_Iter:
{
- Func *func;
- Iter *iter;
+ Iter *iter = (Iter *) first_arg;
- iter = (Iter *) first_arg;
- func = (Func *) ((Expr *) iter->iterexpr)->oper;
- argtype = get_func_rettype(func->funcid);
+ /*
+ * If the argument of the Iter returns a tuple,
+ * funcname may be a projection. If so, we stick
+ * the FieldSelect *inside* the Iter --- this is
+ * klugy, but necessary because ExecTargetList()
+ * currently does the right thing only when the
+ * Iter node is at the top level of a targetlist item.
+ */
+ argtype = iter->itertype;
argrelid = typeidTypeRelid(argtype);
if (argrelid &&
- ((attnum = get_attnum(argrelid, funcname))
- != InvalidAttrNumber))
+ get_attnum(argrelid, funcname) != InvalidAttrNumber)
{
-
- /*
- * the argument is a function returning a tuple, so
- * funcname may be a projection
- */
-
- /* add a tlist to the func node and return the Iter */
- rd = heap_openr_nofail(typeidTypeName(argtype));
- if (RelationIsValid(rd))
- {
- relid = RelationGetRelid(rd);
- func->func_tlist = setup_tlist(funcname, argrelid);
- iter->itertype = attnumTypeId(rd, attnum);
- heap_close(rd, NoLock);
- return (Node *) iter;
- }
- else
- {
- elog(ERROR, "Function '%s' has bad return type %d",
- funcname, argtype);
- }
- }
- else
- {
- /* drop through */
- ;
+ fselect = setup_field_select(iter->iterexpr,
+ funcname, argrelid);
+ iter->iterexpr = (Node *) fselect;
+ iter->itertype = fselect->resulttype;
+ return (Node *) iter;
}
break;
}
@@ -1665,38 +1590,20 @@ ParseComplexProjection(ParseState *pstate,
if (expr->opType != FUNC_EXPR)
break;
- funcnode = (Func *) expr->oper;
- argtype = get_func_rettype(funcnode->funcid);
- argrelid = typeidTypeRelid(argtype);
-
/*
- * the argument is a function returning a tuple, so
+ * If the argument is a function returning a tuple,
* funcname may be a projection
*/
+ funcnode = (Func *) expr->oper;
+ argtype = funcnode->functype;
+ argrelid = typeidTypeRelid(argtype);
if (argrelid &&
- (attnum = get_attnum(argrelid, funcname))
- != InvalidAttrNumber)
+ get_attnum(argrelid, funcname) != InvalidAttrNumber)
{
- Expr *newexpr;
-
- /* add a tlist to the func node */
- rd = heap_openr(typeidTypeName(argtype), NoLock);
-
- relid = RelationGetRelid(rd);
- funcnode->func_tlist = setup_tlist(funcname, argrelid);
- funcnode->functype = attnumTypeId(rd, attnum);
-
- newexpr = makeNode(Expr);
- newexpr->typeOid = funcnode->functype;
- newexpr->opType = FUNC_EXPR;
- newexpr->oper = (Node *) funcnode;
- newexpr->args = expr->args;
-
- heap_close(rd, NoLock);
-
- return (Node *) newexpr;
+ fselect = setup_field_select((Node *) expr,
+ funcname, argrelid);
+ return (Node *) fselect;
}
-
break;
}
case T_Param:
@@ -1707,19 +1614,14 @@ ParseComplexProjection(ParseState *pstate,
* If the Param is a complex type, this could be a
* projection
*/
- rd = heap_openr_nofail(typeidTypeName(param->paramtype));
- if (RelationIsValid(rd))
+ argtype = param->paramtype;
+ argrelid = typeidTypeRelid(argtype);
+ if (argrelid &&
+ get_attnum(argrelid, funcname) != InvalidAttrNumber)
{
- relid = RelationGetRelid(rd);
- if ((attnum = get_attnum(relid, funcname))
- != InvalidAttrNumber)
- {
- param->paramtype = attnumTypeId(rd, attnum);
- param->param_tlist = setup_tlist(funcname, relid);
- heap_close(rd, NoLock);
- return (Node *) param;
- }
- heap_close(rd, NoLock);
+ fselect = setup_field_select((Node *) param,
+ funcname, argrelid);
+ return (Node *) fselect;
}
break;
}
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 273dc0ef644..2bda101538c 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.43 2000/07/05 23:11:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.44 2000/08/08 15:42:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -161,9 +161,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
newop = makeOper(oprid(tup),/* opno */
InvalidOid,/* opid */
- opform->oprresult, /* operator result type */
- 0,
- NULL);
+ opform->oprresult); /* operator result type */
result = makeNode(Expr);
result->typeOid = opform->oprresult;
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 7a3e3c2d6ad..802299c8966 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.45 2000/07/02 22:00:41 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.46 2000/08/08 15:42:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -412,8 +412,6 @@ expandAll(ParseState *pstate, char *relname, Attr *ref, int *this_resno)
varnode->vartype,
varnode->vartypmod,
label,
- (Index) 0,
- (Oid) 0,
false);
te->expr = (Node *) varnode;
te_list = lappend(te_list, te);
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 2f076028cc9..1564f976b04 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.60 2000/06/15 03:32:20 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.61 2000/08/08 15:42:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -71,8 +71,6 @@ transformTargetEntry(ParseState *pstate,
type_id,
type_mod,
colname,
- (Index) 0,
- (Oid) InvalidOid,
resjunk);
return makeTargetEntry(resnode, expr);