diff options
| author | Tom Lane | 2002-08-29 00:17:06 +0000 |
|---|---|---|
| committer | Tom Lane | 2002-08-29 00:17:06 +0000 |
| commit | 64505ed58ba71df3221e2467dc458af2e1912895 (patch) | |
| tree | 3c110a6d9e3badd87d741976871028760b8f55b5 /src/backend/parser | |
| parent | 7483749d8207c0cbcce5ce69161400ace31a6856 (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.y | 64 | ||||
| -rw-r--r-- | src/backend/parser/parse_relation.c | 255 |
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: |
