1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-22 21:53:06 +03:00

Code review for standalone composite types, query-specified composite

types, SRFs.  Not happy with memory management yet, but I'll commit these
other changes.
This commit is contained in:
Tom Lane
2002-08-29 00:17:06 +00:00
parent 7483749d82
commit 64505ed58b
41 changed files with 836 additions and 744 deletions

View File

@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.363 2002/08/28 20:46:23 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.364 2002/08/29 00:17:04 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -204,8 +204,8 @@ static void doNegateFloat(Value *v);
%type <list> stmtblock, stmtmulti,
OptTableElementList, TableElementList, OptInherit, definition,
opt_distinct, opt_definition, func_args, rowdefinition
func_args_list, func_as, createfunc_opt_list
opt_distinct, opt_definition, func_args,
func_args_list, func_as, createfunc_opt_list,
oper_argtypes, RuleActionList, RuleActionMulti,
opt_column_list, columnList, opt_name_list,
sort_clause, opt_sort_clause, sortby_list, index_params,
@@ -216,7 +216,7 @@ static void doNegateFloat(Value *v);
insert_target_list, def_list, opt_indirection,
group_clause, TriggerFuncArgs, select_limit,
opt_select_limit, opclass_item_list, trans_options,
TableFuncElementList, OptTableFuncElementList,
TableFuncElementList,
convert_args, prep_type_clause, prep_type_list,
execute_param_clause, execute_param_list
@@ -1424,14 +1424,14 @@ OptTableElementList:
;
TableElementList:
TableElementList ',' TableElement
{
$$ = lappend($1, $3);
}
| TableElement
TableElement
{
$$ = makeList1($1);
}
| TableElementList ',' TableElement
{
$$ = lappend($1, $3);
}
;
TableElement:
@@ -2234,11 +2234,12 @@ DefineStmt:
n->definition = $4;
$$ = (Node *)n;
}
| CREATE TYPE_P any_name AS rowdefinition
| CREATE TYPE_P any_name AS '(' TableFuncElementList ')'
{
CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
RangeVar *r = makeNode(RangeVar);
/* can't use qualified_name, sigh */
switch (length($3))
{
case 1:
@@ -2258,13 +2259,12 @@ DefineStmt:
break;
default:
elog(ERROR,
"Improper qualified name "
"(too many dotted names): %s",
"Improper qualified name (too many dotted names): %s",
NameListToString($3));
break;
}
n->typevar = r;
n->coldeflist = $5;
n->coldeflist = $6;
$$ = (Node *)n;
}
| CREATE CHARACTER SET opt_as any_name GET definition opt_collate
@@ -2277,9 +2277,6 @@ DefineStmt:
}
;
rowdefinition: '(' TableFuncElementList ')' { $$ = $2; }
;
definition: '(' def_list ')' { $$ = $2; }
;
@@ -4539,14 +4536,22 @@ table_ref: relation_expr
n->coldeflist = NIL;
$$ = (Node *) n;
}
| func_table AS '(' OptTableFuncElementList ')'
| func_table alias_clause
{
RangeFunction *n = makeNode(RangeFunction);
n->funccallnode = $1;
n->alias = $2;
n->coldeflist = NIL;
$$ = (Node *) n;
}
| func_table AS '(' TableFuncElementList ')'
{
RangeFunction *n = makeNode(RangeFunction);
n->funccallnode = $1;
n->coldeflist = $4;
$$ = (Node *) n;
}
| func_table AS ColId '(' OptTableFuncElementList ')'
| func_table AS ColId '(' TableFuncElementList ')'
{
RangeFunction *n = makeNode(RangeFunction);
Alias *a = makeNode(Alias);
@@ -4556,7 +4561,7 @@ table_ref: relation_expr
n->coldeflist = $5;
$$ = (Node *) n;
}
| func_table ColId '(' OptTableFuncElementList ')'
| func_table ColId '(' TableFuncElementList ')'
{
RangeFunction *n = makeNode(RangeFunction);
Alias *a = makeNode(Alias);
@@ -4566,14 +4571,6 @@ table_ref: relation_expr
n->coldeflist = $4;
$$ = (Node *) n;
}
| func_table alias_clause
{
RangeFunction *n = makeNode(RangeFunction);
n->funccallnode = $1;
n->alias = $2;
n->coldeflist = NIL;
$$ = (Node *) n;
}
| select_with_parens
{
/*
@@ -4815,25 +4812,19 @@ func_table: func_name '(' ')'
where_clause:
WHERE a_expr { $$ = $2; }
/* no qualifiers */
| /*EMPTY*/ { $$ = NULL; }
;
OptTableFuncElementList:
TableFuncElementList { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; }
;
TableFuncElementList:
TableFuncElementList ',' TableFuncElement
{
$$ = lappend($1, $3);
}
| TableFuncElement
TableFuncElement
{
$$ = makeList1($1);
}
| TableFuncElementList ',' TableFuncElement
{
$$ = lappend($1, $3);
}
;
TableFuncElement: ColId Typename
@@ -4842,7 +4833,6 @@ TableFuncElement: ColId Typename
n->colname = $1;
n->typename = $2;
n->constraints = NIL;
$$ = (Node *)n;
}
;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.77 2002/08/08 17:00:19 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.78 2002/08/29 00:17:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -900,17 +900,14 @@ addRangeTableEntryForFunction(ParseState *pstate,
* Now determine if the function returns a simple or composite type,
* and check/add column aliases.
*/
functyptype = get_typtype(funcrettype);
if (coldeflist != NIL)
{
/*
* we *only* allow a coldeflist for functions returning a
* RECORD pseudo-type
*/
if (functyptype != 'p' || (functyptype == 'p' && funcrettype != RECORDOID))
elog(ERROR, "A column definition list is only allowed for"
" functions returning RECORD");
if (funcrettype != RECORDOID)
elog(ERROR, "A column definition list is only allowed for functions returning RECORD");
}
else
{
@@ -918,57 +915,55 @@ addRangeTableEntryForFunction(ParseState *pstate,
* ... and a coldeflist is *required* for functions returning a
* RECORD pseudo-type
*/
if (functyptype == 'p' && funcrettype == RECORDOID)
elog(ERROR, "A column definition list is required for functions"
" returning RECORD");
if (funcrettype == RECORDOID)
elog(ERROR, "A column definition list is required for functions returning RECORD");
}
functyptype = get_typtype(funcrettype);
if (functyptype == 'c')
{
/*
* Named composite data type, i.e. a table's row type
*/
Oid funcrelid = typeidTypeRelid(funcrettype);
Relation rel;
int maxattrs;
if (OidIsValid(funcrelid))
if (!OidIsValid(funcrelid))
elog(ERROR, "Invalid typrelid for complex type %u",
funcrettype);
/*
* Get the rel's relcache entry. This access ensures that we have an
* up-to-date relcache entry for the rel.
*/
rel = relation_open(funcrelid, AccessShareLock);
/*
* Since the rel is open anyway, let's check that the number of column
* aliases is reasonable.
*/
maxattrs = RelationGetNumberOfAttributes(rel);
if (maxattrs < numaliases)
elog(ERROR, "Table \"%s\" has %d columns available but %d columns specified",
RelationGetRelationName(rel), maxattrs, numaliases);
/* fill in alias columns using actual column names */
for (varattno = numaliases; varattno < maxattrs; varattno++)
{
/*
* Get the rel's relcache entry. This access ensures that we have an
* up-to-date relcache entry for the rel.
*/
Relation rel;
int maxattrs;
char *attrname;
rel = heap_open(funcrelid, AccessShareLock);
/*
* Since the rel is open anyway, let's check that the number of column
* aliases is reasonable.
*/
maxattrs = RelationGetNumberOfAttributes(rel);
if (maxattrs < numaliases)
elog(ERROR, "Table \"%s\" has %d columns available but %d columns specified",
RelationGetRelationName(rel), maxattrs, numaliases);
/* fill in alias columns using actual column names */
for (varattno = numaliases; varattno < maxattrs; varattno++)
{
char *attrname;
attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname));
eref->colnames = lappend(eref->colnames, makeString(attrname));
}
/*
* Drop the rel refcount, but keep the access lock till end of
* transaction so that the table can't be deleted or have its schema
* modified underneath us.
*/
heap_close(rel, NoLock);
attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname));
eref->colnames = lappend(eref->colnames, makeString(attrname));
}
else
elog(ERROR, "Invalid return relation specified for function %s",
funcname);
/*
* Drop the rel refcount, but keep the access lock till end of
* transaction so that the table can't be deleted or have its schema
* modified underneath us.
*/
relation_close(rel, NoLock);
}
else if (functyptype == 'b' || functyptype == 'd')
{
@@ -986,10 +981,12 @@ addRangeTableEntryForFunction(ParseState *pstate,
{
List *col;
/* Use the column definition list to form the alias list */
eref->colnames = NIL;
foreach(col, coldeflist)
{
char *attrname;
ColumnDef *n = lfirst(col);
char *attrname;
attrname = pstrdup(n->colname);
eref->colnames = lappend(eref->colnames, makeString(attrname));
@@ -1277,63 +1274,58 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
char functyptype = get_typtype(funcrettype);
List *coldeflist = rte->coldeflist;
/*
* Build a suitable tupledesc representing the output rows
*/
if (functyptype == 'c')
{
/*
* Composite data type, i.e. a table's row type
* Same as ordinary relation RTE
*/
Oid funcrelid = typeidTypeRelid(funcrettype);
if (OidIsValid(funcrelid))
Relation rel;
int maxattrs;
int numaliases;
if (!OidIsValid(funcrelid))
elog(ERROR, "Invalid typrelid for complex type %u",
funcrettype);
rel = relation_open(funcrelid, AccessShareLock);
maxattrs = RelationGetNumberOfAttributes(rel);
numaliases = length(rte->eref->colnames);
for (varattno = 0; varattno < maxattrs; varattno++)
{
/*
* Composite data type, i.e. a table's row type
* Same as ordinary relation RTE
*/
Relation rel;
int maxattrs;
int numaliases;
Form_pg_attribute attr = rel->rd_att->attrs[varattno];
rel = heap_open(funcrelid, AccessShareLock);
maxattrs = RelationGetNumberOfAttributes(rel);
numaliases = length(rte->eref->colnames);
if (attr->attisdropped)
continue;
for (varattno = 0; varattno < maxattrs; varattno++)
if (colnames)
{
Form_pg_attribute attr = rel->rd_att->attrs[varattno];
char *label;
if (attr->attisdropped)
continue;
if (colnames)
{
char *label;
if (varattno < numaliases)
label = strVal(nth(varattno, rte->eref->colnames));
else
label = NameStr(attr->attname);
*colnames = lappend(*colnames, makeString(pstrdup(label)));
}
if (colvars)
{
Var *varnode;
varnode = makeVar(rtindex,
attr->attnum,
attr->atttypid,
attr->atttypmod,
sublevels_up);
*colvars = lappend(*colvars, varnode);
}
if (varattno < numaliases)
label = strVal(nth(varattno, rte->eref->colnames));
else
label = NameStr(attr->attname);
*colnames = lappend(*colnames, makeString(pstrdup(label)));
}
heap_close(rel, AccessShareLock);
if (colvars)
{
Var *varnode;
varnode = makeVar(rtindex,
attr->attnum,
attr->atttypid,
attr->atttypmod,
sublevels_up);
*colvars = lappend(*colvars, varnode);
}
}
else
elog(ERROR, "Invalid return relation specified"
" for function");
relation_close(rel, AccessShareLock);
}
else if (functyptype == 'b' || functyptype == 'd')
{
@@ -1376,12 +1368,9 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
if (colvars)
{
Var *varnode;
HeapTuple typeTuple;
Oid atttypid;
typeTuple = typenameType(colDef->typename);
atttypid = HeapTupleGetOid(typeTuple);
ReleaseSysCache(typeTuple);
atttypid = typenameTypeId(colDef->typename);
varnode = makeVar(rtindex,
attnum,
@@ -1394,8 +1383,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
}
}
else
elog(ERROR, "Unknown kind of return type specified"
" for function");
elog(ERROR, "Unknown kind of return type specified for function");
}
break;
case RTE_JOIN:
@@ -1595,9 +1583,6 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
char functyptype = get_typtype(funcrettype);
List *coldeflist = rte->coldeflist;
/*
* Build a suitable tupledesc representing the output rows
*/
if (functyptype == 'c')
{
/*
@@ -1605,36 +1590,33 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
* Same as ordinary relation RTE
*/
Oid funcrelid = typeidTypeRelid(funcrettype);
HeapTuple tp;
Form_pg_attribute att_tup;
if (OidIsValid(funcrelid))
{
HeapTuple tp;
Form_pg_attribute att_tup;
if (!OidIsValid(funcrelid))
elog(ERROR, "Invalid typrelid for complex type %u",
funcrettype);
tp = SearchSysCache(ATTNUM,
ObjectIdGetDatum(funcrelid),
Int16GetDatum(attnum),
0, 0);
/* this shouldn't happen... */
if (!HeapTupleIsValid(tp))
elog(ERROR, "Relation %s does not have attribute %d",
get_rel_name(funcrelid), attnum);
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
/*
* If dropped column, pretend it ain't there. See notes
* in scanRTEForColumn.
*/
if (att_tup->attisdropped)
elog(ERROR, "Relation \"%s\" has no column \"%s\"",
get_rel_name(funcrelid),
NameStr(att_tup->attname));
*vartype = att_tup->atttypid;
*vartypmod = att_tup->atttypmod;
ReleaseSysCache(tp);
}
else
elog(ERROR, "Invalid return relation specified"
" for function");
tp = SearchSysCache(ATTNUM,
ObjectIdGetDatum(funcrelid),
Int16GetDatum(attnum),
0, 0);
/* this shouldn't happen... */
if (!HeapTupleIsValid(tp))
elog(ERROR, "Relation \"%s\" does not have attribute %d",
get_rel_name(funcrelid), attnum);
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
/*
* If dropped column, pretend it ain't there. See notes
* in scanRTEForColumn.
*/
if (att_tup->attisdropped)
elog(ERROR, "Relation \"%s\" has no column \"%s\"",
get_rel_name(funcrelid),
NameStr(att_tup->attname));
*vartype = att_tup->atttypid;
*vartypmod = att_tup->atttypmod;
ReleaseSysCache(tp);
}
else if (functyptype == 'b' || functyptype == 'd')
{
@@ -1647,19 +1629,12 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
else if (functyptype == 'p' && funcrettype == RECORDOID)
{
ColumnDef *colDef = nth(attnum - 1, coldeflist);
HeapTuple typeTuple;
Oid atttypid;
typeTuple = typenameType(colDef->typename);
atttypid = HeapTupleGetOid(typeTuple);
ReleaseSysCache(typeTuple);
*vartype = atttypid;
*vartype = typenameTypeId(colDef->typename);
*vartypmod = -1;
}
else
elog(ERROR, "Unknown kind of return type specified"
" for function");
elog(ERROR, "Unknown kind of return type specified for function");
}
break;
case RTE_JOIN: