summaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
authorTom Lane2002-08-29 00:17:06 +0000
committerTom Lane2002-08-29 00:17:06 +0000
commit64505ed58ba71df3221e2467dc458af2e1912895 (patch)
tree3c110a6d9e3badd87d741976871028760b8f55b5 /src/backend/parser
parent7483749d8207c0cbcce5ce69161400ace31a6856 (diff)
Code review for standalone composite types, query-specified composite
types, SRFs. Not happy with memory management yet, but I'll commit these other changes.
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/gram.y64
-rw-r--r--src/backend/parser/parse_relation.c255
2 files changed, 142 insertions, 177 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 561145bb97d..463a8d5a4e5 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -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,13 +1424,13 @@ OptTableElementList:
;
TableElementList:
- TableElementList ',' TableElement
+ TableElement
{
- $$ = lappend($1, $3);
+ $$ = makeList1($1);
}
- | TableElement
+ | TableElementList ',' TableElement
{
- $$ = makeList1($1);
+ $$ = lappend($1, $3);
}
;
@@ -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,24 +4812,18 @@ func_table: func_name '(' ')'
where_clause:
WHERE a_expr { $$ = $2; }
- /* no qualifiers */
| /*EMPTY*/ { $$ = NULL; }
;
-OptTableFuncElementList:
- TableFuncElementList { $$ = $1; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
-
TableFuncElementList:
- TableFuncElementList ',' TableFuncElement
+ TableFuncElement
{
- $$ = lappend($1, $3);
+ $$ = makeList1($1);
}
- | TableFuncElement
+ | TableFuncElementList ',' TableFuncElement
{
- $$ = makeList1($1);
+ $$ = lappend($1, $3);
}
;
@@ -4842,7 +4833,6 @@ TableFuncElement: ColId Typename
n->colname = $1;
n->typename = $2;
n->constraints = NIL;
-
$$ = (Node *)n;
}
;
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 6713c665098..174c05790d9 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.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))
- {
- /*
- * 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;
+ if (!OidIsValid(funcrelid))
+ elog(ERROR, "Invalid typrelid for complex type %u",
+ funcrettype);
- 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);
+ /*
+ * 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);
- /* fill in alias columns using actual column names */
- for (varattno = numaliases; varattno < maxattrs; varattno++)
- {
- char *attrname;
+ /*
+ * 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);
- attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname));
- eref->colnames = lappend(eref->colnames, makeString(attrname));
- }
+ /* fill in alias columns using actual column names */
+ for (varattno = numaliases; varattno < maxattrs; varattno++)
+ {
+ char *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;
-
- rel = heap_open(funcrelid, AccessShareLock);
- maxattrs = RelationGetNumberOfAttributes(rel);
- numaliases = length(rte->eref->colnames);
-
- for (varattno = 0; varattno < maxattrs; varattno++)
+ Form_pg_attribute attr = rel->rd_att->attrs[varattno];
+
+ if (attr->attisdropped)
+ continue;
+
+ if (colnames)
{
- Form_pg_attribute attr = rel->rd_att->attrs[varattno];
-
- 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);
- }
+ char *label;
+
+ 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;
-
- 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");
+ 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 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: