1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-06 07:49:08 +03:00

Parser Overhaul

This commit is contained in:
Bruce Momjian
1996-10-30 02:02:41 +00:00
parent 1dfe4eaeb1
commit f59a46a8c8
10 changed files with 409 additions and 492 deletions

View File

@@ -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;
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);
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);
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);
}