diff options
author | Bruce Momjian <bruce@momjian.us> | 1996-10-30 02:02:41 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1996-10-30 02:02:41 +0000 |
commit | f59a46a8c81caad3c47a3595bd1712658b7c1f25 (patch) | |
tree | 1281813811c918f065492ce385a0947346f24a15 /src/backend/parser/parse_query.c | |
parent | 1dfe4eaeb1c5e3f823e71e32c88ec4794fee1dde (diff) | |
download | postgresql-f59a46a8c81caad3c47a3595bd1712658b7c1f25.tar.gz postgresql-f59a46a8c81caad3c47a3595bd1712658b7c1f25.zip |
Parser Overhaul
Diffstat (limited to 'src/backend/parser/parse_query.c')
-rw-r--r-- | src/backend/parser/parse_query.c | 275 |
1 files changed, 191 insertions, 84 deletions
diff --git a/src/backend/parser/parse_query.c b/src/backend/parser/parse_query.c index 81480b1d1f0..179186d5d70 100644 --- a/src/backend/parser/parse_query.c +++ b/src/backend/parser/parse_query.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.4 1996/08/28 22:50:24 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.5 1996/10/30 02:01:59 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -40,55 +40,96 @@ Oid *param_type_info; int pfunc_num_args; -extern int Quiet; +/* given refname, return a pointer to the range table entry */ +RangeTblEntry * +refnameRangeTableEntry(List *rtable, char *refname) +{ + List *temp; + + foreach(temp, rtable) { + RangeTblEntry *rte = lfirst(temp); + if (!strcmp(rte->refname, refname)) + return rte; + } + return NULL; +} -/* given range variable, return id of variable; position starts with 1 */ +/* given refname, return id of variable; position starts with 1 */ int -RangeTablePosn(List *rtable, char *rangevar) +refnameRangeTablePosn(List *rtable, char *refname) { int index; List *temp; index = 1; -/* temp = pstate->p_rtable; */ - temp = rtable; - while (temp != NIL) { - RangeTblEntry *rt_entry = lfirst(temp); + foreach(temp, rtable) { + RangeTblEntry *rte = lfirst(temp); - if (!strcmp(rt_entry->refname, rangevar)) + if (!strcmp(rte->refname, refname)) return index; - - temp = lnext(temp); index++; } return(0); } -char* -VarnoGetRelname(ParseState *pstate, int vnum) +/* + * returns range entry if found, else NULL + */ +RangeTblEntry * +colnameRangeTableEntry(ParseState *pstate, char *colname) { - int i; - List *temp = pstate->p_rtable; - for( i = 1; i < vnum ; i++) - temp = lnext(temp); - return(((RangeTblEntry*)lfirst(temp))->relname); + List *et; + List *rtable; + RangeTblEntry *rte_result; + + if (pstate->p_is_rule) + rtable = lnext(lnext(pstate->p_rtable)); + else + rtable = pstate->p_rtable; + + rte_result = NULL; + foreach(et, rtable) { + RangeTblEntry *rte = lfirst(et); + + /* only entries on outer(non-function?) scope */ + if (!rte->inFromCl && rte != pstate->p_target_rangetblentry) + continue; + + if (get_attnum(rte->relid, colname) != InvalidAttrNumber) { + if (rte_result != NULL) { + if (!pstate->p_is_insert || + rte != pstate->p_target_rangetblentry) + elog(WARN, "Column %s is ambiguous", colname); + } + else rte_result = rte; + } + } + return rte_result; } - +/* + * put new entry in pstate p_rtable structure, or return pointer + * if pstate null +*/ RangeTblEntry * -makeRangeTableEntry(char *relname, - bool inh, - TimeRange *timeRange, - char *refname) +addRangeTableEntry(ParseState *pstate, + char *relname, + char *refname, + bool inh, bool inFromCl, + TimeRange *timeRange) { Relation relation; - RangeTblEntry *ent = makeNode(RangeTblEntry); + RangeTblEntry *rte = makeNode(RangeTblEntry); - ent->relname = pstrdup(relname); - ent->refname = refname; + if (pstate != NULL && + refnameRangeTableEntry(pstate->p_rtable, refname) != NULL) + elog(WARN,"Table name %s specified more than once",refname); + + rte->relname = pstrdup(relname); + rte->refname = pstrdup(refname); - relation = heap_openr(ent->relname); + relation = heap_openr(relname); if (relation == NULL) { elog(WARN,"%s: %s", relname, ACL_NO_PRIV_WARNING); @@ -99,18 +140,26 @@ makeRangeTableEntry(char *relname, * or recursive (transitive closure) * [we don't support them all -- ay 9/94 ] */ - ent->inh = inh; + rte->inh = inh; - ent->timeRange = timeRange; + rte->timeRange = timeRange; /* RelOID */ - ent->relid = RelationGetRelationId(relation); + rte->relid = RelationGetRelationId(relation); + + rte->archive = false; + + rte->inFromCl = inFromCl; /* * close the relation we're done with it for now. */ + if (pstate != NULL) + pstate->p_rtable = lappend(pstate->p_rtable, rte); + heap_close(relation); - return ent; + + return rte; } /* @@ -119,65 +168,59 @@ makeRangeTableEntry(char *relname, * assumes reldesc caching works */ List * -expandAll(ParseState* pstate, char *relname, int *this_resno) +expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno) { Relation rdesc; - List *tall = NIL; + List *te_tail = NIL, *te_head = NIL; Var *varnode; - int i, maxattrs, first_resno; - int type_id, type_len, vnum; - char *physical_relname; - - first_resno = *this_resno; - - /* printf("\nExpanding %.*s.all\n", NAMEDATALEN, relname); */ - vnum = RangeTablePosn(pstate->p_rtable, relname); - if ( vnum == 0 ) { - pstate->p_rtable = lappend(pstate->p_rtable, - makeRangeTableEntry(relname, FALSE, NULL, - relname)); - vnum = RangeTablePosn(pstate->p_rtable, relname); - } - - physical_relname = VarnoGetRelname(pstate, vnum); + int varattno, maxattrs; + int type_id, type_len; + RangeTblEntry *rte; + + rte = refnameRangeTableEntry(pstate->p_rtable, refname); + if (rte == NULL) + rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE, NULL); - rdesc = heap_openr(physical_relname); + rdesc = heap_open(rte->relid); if (rdesc == NULL ) { - elog(WARN,"Unable to expand all -- heap_openr failed on %s", - physical_relname); + elog(WARN,"Unable to expand all -- heap_open failed on %s", + rte->refname); return NIL; } maxattrs = RelationGetNumberOfAttributes(rdesc); - for ( i = maxattrs-1 ; i > -1 ; --i ) { + for ( varattno = 0; varattno <= maxattrs-1 ; varattno++ ) { char *attrname; - TargetEntry *rte = makeNode(TargetEntry); + char *resname = NULL; + TargetEntry *te = makeNode(TargetEntry); - attrname = pstrdup ((rdesc->rd_att->attrs[i]->attname).data); - varnode = (Var*)make_var(pstate, relname, attrname, &type_id); + attrname = pstrdup ((rdesc->rd_att->attrs[varattno]->attname).data); + varnode = (Var*)make_var(pstate, refname, attrname, &type_id); type_len = (int)tlen(get_id_type(type_id)); + handleTargetColname(pstate, &resname, refname, attrname); + if (resname != NULL) + attrname = resname; + /* Even if the elements making up a set are complex, the * set itself is not. */ - rte->resdom = makeResdom((AttrNumber) i + first_resno, + te->resdom = makeResdom((AttrNumber) (*this_resno)++, (Oid)type_id, (Size)type_len, attrname, (Index)0, (Oid)0, 0); - rte->expr = (Node *)varnode; - tall = lcons(rte, tall); + te->expr = (Node *)varnode; + if (te_head == NIL) + te_head = te_tail = lcons(te, NIL); + else te_tail = lappend(te_tail, te); } - /* - * Close the reldesc - we're done with it now - */ heap_close(rdesc); - *this_resno = first_resno + maxattrs; - return(tall); + return(te_head); } TimeQual @@ -385,27 +428,21 @@ find_atttype(Oid relid, char *attrname) Var * -make_var(ParseState *pstate, char *relname, char *attrname, int *type_id) +make_var(ParseState *pstate, char *refname, char *attrname, int *type_id) { Var *varnode; int vnum, attid, vartypeid; Relation rd; - - vnum = RangeTablePosn(pstate->p_rtable, relname); - - if (vnum == 0) { - pstate->p_rtable = - lappend(pstate->p_rtable, - makeRangeTableEntry(relname, FALSE, - NULL, relname)); - vnum = RangeTablePosn (pstate->p_rtable, relname); - relname = VarnoGetRelname(pstate, vnum); - } else { - relname = VarnoGetRelname(pstate, vnum); - } - - rd = heap_openr(relname); -/* relid = RelationGetRelationId(rd); */ + RangeTblEntry *rte; + + rte = refnameRangeTableEntry(pstate->p_rtable, refname); + if (rte == NULL) + rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE, NULL); + + vnum = refnameRangeTablePosn(pstate->p_rtable, refname); + + rd = heap_open(rte->relid); + attid = nf_varattno(rd, (char *) attrname); if (attid == InvalidAttrNumber) elog(WARN, "Invalid attribute %s\n", attrname); @@ -413,9 +450,6 @@ make_var(ParseState *pstate, char *relname, char *attrname, int *type_id) varnode = makeVar(vnum, attid, vartypeid, vnum, attid); - /* - * close relation we're done with it now - */ heap_close(rd); *type_id = vartypeid; @@ -655,3 +689,76 @@ param_type(int t) return param_type_info[t-1]; } +/* + * handleTargetColname - + * use column names from insert + */ +void +handleTargetColname(ParseState *pstate, char **resname, + char *refname, char *colname) +{ + if (pstate->p_is_insert) { + if (pstate->p_insert_columns != NIL ) { + Ident *id = lfirst(pstate->p_insert_columns); + Assert(lfirst(pstate->p_insert_columns) != NIL); + *resname = id->name; + pstate->p_insert_columns = lnext(pstate->p_insert_columns); + } + else + elog(WARN, "insert: more expressions than target columns"); + } + if (pstate->p_is_insert||pstate->p_is_update) + checkTargetTypes(pstate, *resname, refname, colname); +} + +/* + * checkTargetTypes - + * checks value and target column types + */ +void +checkTargetTypes(ParseState *pstate, char *target_colname, + char *refname, char *colname) +{ + int attrtype_id, attrtype_target, resdomno_id, resdomno_target; + Relation rd; + RangeTblEntry *rte; + + if (target_colname == NULL || colname == NULL) + return; + + if (refname != NULL) + rte = refnameRangeTableEntry(pstate->p_rtable, refname); + else { + rte = colnameRangeTableEntry(pstate, colname); + refname = rte->refname; + } + + Assert(refname != NULL && rte != NULL); + + Assert(rte != NULL); +/* + if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry) + elog(WARN, "%s not available in this context", colname); +*/ + rd = heap_open(rte->relid); + Assert(RelationIsValid(rd)); + + resdomno_id = varattno(rd,colname); + attrtype_id = att_typeid(rd,resdomno_id); + + resdomno_target = varattno(pstate->p_target_relation,target_colname); + attrtype_target = att_typeid(pstate->p_target_relation, resdomno_target); + + if (attrtype_id != attrtype_target) + elog(WARN, "Type of %s does not match target column %s", + colname, target_colname); + + if ((attrtype_id == BPCHAROID || attrtype_id == VARCHAROID) && + rd->rd_att->attrs[resdomno_id-1]->attlen != + pstate->p_target_relation->rd_att->attrs[resdomno_target-1]->attlen) + elog(WARN, "Length of %s does not match length of target column %s", + colname, target_colname); + + heap_close(rd); +} + |