diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/commands/creatinh.c | 46 | ||||
-rw-r--r-- | src/backend/commands/variable.c | 52 | ||||
-rw-r--r-- | src/backend/executor/nodeAppend.c | 9 | ||||
-rw-r--r-- | src/backend/nodes/list.c | 17 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 17 | ||||
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 25 | ||||
-rw-r--r-- | src/backend/parser/analyze.c | 8 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 94 | ||||
-rw-r--r-- | src/backend/parser/keywords.c | 7 | ||||
-rw-r--r-- | src/backend/parser/parse_clause.c | 6 | ||||
-rw-r--r-- | src/bin/pgaccess/lib/help/create_table.hlp | 2 | ||||
-rw-r--r-- | src/bin/pgaccess/lib/help/inheritance.hlp | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_attribute.h | 8 | ||||
-rw-r--r-- | src/include/catalog/pg_class.h | 38 | ||||
-rw-r--r-- | src/include/commands/variable.h | 3 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 4 | ||||
-rw-r--r-- | src/include/nodes/pg_list.h | 3 | ||||
-rw-r--r-- | src/include/parser/parse_clause.h | 4 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/keywords.c | 3 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/preproc.y | 15 | ||||
-rw-r--r-- | src/test/regress/sql/run_check.tests | 1 |
21 files changed, 284 insertions, 80 deletions
diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c index b8f8a56eafd..f33d301ded2 100644 --- a/src/backend/commands/creatinh.c +++ b/src/backend/commands/creatinh.c @@ -8,7 +8,11 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.58 2000/05/30 00:49:43 momjian Exp $ +<<<<<<< creatinh.c + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.59 2000/06/09 01:44:03 momjian Exp $ +======= + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.59 2000/06/09 01:44:03 momjian Exp $ +>>>>>>> 1.58 * *------------------------------------------------------------------------- */ @@ -34,6 +38,9 @@ static bool checkAttrExists(const char *attributeName, const char *attributeType, List *schema); static List *MergeAttributes(List *schema, List *supers, List **supconstr); static void StoreCatalogInheritance(Oid relationId, List *supers); +static void +setRelhassubclassInRelation(Oid relationId, bool relhassubclass); + /* ---------------------------------------------------------------- * DefineRelation @@ -326,6 +333,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr) TupleConstr *constr; relation = heap_openr(name, AccessShareLock); + setRelhassubclassInRelation(relation->rd_id, true); tupleDesc = RelationGetDescr(relation); constr = tupleDesc->constr; @@ -660,3 +668,39 @@ checkAttrExists(const char *attributeName, const char *attributeType, List *sche } return false; } + + +static void +setRelhassubclassInRelation(Oid relationId, bool relhassubclass) +{ + Relation relationRelation; + HeapTuple tuple; + Relation idescs[Num_pg_class_indices]; + + /* + * Lock a relation given its Oid. Go to the RelationRelation (i.e. + * pg_relation), find the appropriate tuple, and add the specified + * lock to it. + */ + relationRelation = heap_openr(RelationRelationName, RowExclusiveLock); + tuple = SearchSysCacheTuple(RELOID, + ObjectIdGetDatum(relationId), + 0, 0, 0) +; + Assert(HeapTupleIsValid(tuple)); + + ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass = relhassubclass; + heap_update(relationRelation, &tuple->t_self, tuple, NULL); + + /* keep the catalog indices up to date */ + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, tuple +); + CatalogCloseIndices(Num_pg_class_indices, idescs); + + heap_close(relationRelation, RowExclusiveLock); +} + + + + diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index 18b39d66aac..aeddade12ec 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.35 2000/05/31 00:28:15 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.36 2000/06/09 01:44:03 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -49,7 +49,12 @@ static bool parse_XactIsoLevel(char *); static bool parse_random_seed(char *); static bool show_random_seed(void); static bool reset_random_seed(void); +static bool parse_examine_subclass(char *); +static bool show_examine_subclass(void); +static bool reset_examine_subclass(void); +#define examine_subclass_default true +bool examine_subclass = examine_subclass_default; /* * get_token @@ -164,6 +169,44 @@ get_token(char **tok, char **val, char *str) return str; } +/* + * + * EXAMINE_SUBCLASS + * + */ +#define EXAMINE_SUBCLASS "EXAMINE_SUBCLASS" + +static bool +parse_examine_subclass(char *value) +{ + if (strcasecmp(value, "on") == 0) + examine_subclass = true; + else if (strcasecmp(value, "off") == 0) + examine_subclass = false; + else if (strcasecmp(value, "default") == 0) + examine_subclass = examine_subclass_default; + else + elog(ERROR, "Bad value for %s (%s)", EXAMINE_SUBCLASS, value); + return TRUE; +} + +static bool +show_examine_subclass() +{ + + if (examine_subclass) + elog(NOTICE, "%s is ON", EXAMINE_SUBCLASS); + else + elog(NOTICE, "%s is OFF", EXAMINE_SUBCLASS); + return TRUE; +} + +static bool +reset_examine_subclass(void) +{ + examine_subclass = examine_subclass_default; + return TRUE; +} /* * DATE_STYLE @@ -545,6 +588,8 @@ SetPGVariable(const char *name, const char *value) #endif else if (strcasecmp(name, "random_seed")==0) parse_random_seed(pstrdup(value)); + else if (strcasecmp(name, "examine_subclass")==0) + parse_examine_subclass(pstrdup(value)); else SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET); } @@ -567,6 +612,8 @@ GetPGVariable(const char *name) #endif else if (strcasecmp(name, "random_seed")==0) show_random_seed(); + else if (strcasecmp(name, "examine_subclass")==0) + show_examine_subclass(); else { const char * val = GetConfigOption(name, superuser()); @@ -574,7 +621,6 @@ GetPGVariable(const char *name) } } - void ResetPGVariable(const char *name) { @@ -592,6 +638,8 @@ ResetPGVariable(const char *name) #endif else if (strcasecmp(name, "random_seed")==0) reset_random_seed(); + else if (strcasecmp(name, "examine_subclass")==0) + reset_examine_subclass(); else SetConfigOption(name, NULL, superuser() ? PGC_SUSET : PGC_USERSET); } diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 1200d9e6ba9..07759293a28 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.30 2000/04/12 17:15:09 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.31 2000/06/09 01:44:09 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -268,7 +268,12 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) resultList = lcons(rri, resultList); } - appendstate->as_result_relation_info_list = resultList; + /* + The as_result_relation_info_list must be in the same + order as the rtentry list otherwise update or delete on + inheritance hierarchies won't work. + */ + appendstate->as_result_relation_info_list = lreverse(resultList); } /* ---------------- * call ExecInitNode on each of the plans in our list diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c index 66d69199beb..45f42dc5024 100644 --- a/src/backend/nodes/list.c +++ b/src/backend/nodes/list.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.31 2000/04/12 17:15:16 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.32 2000/06/09 01:44:12 momjian Exp $ * * NOTES * XXX a few of the following functions are duplicated to handle @@ -523,6 +523,21 @@ set_differencei(List *l1, List *l2) } /* + * Reverse a list, non-destructively + */ +List * +lreverse(List *l) +{ + List *result = NIL; + List *i; + foreach(i, l) + { + result = lcons(lfirst(i), result); + } + return result; +} + +/* * Return t if two integer lists have no members in common. */ bool diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index adb1bce37ee..91ce6f99c1b 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.80 2000/05/30 00:49:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.81 2000/06/09 01:44:14 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -106,6 +106,9 @@ planner(Query *parse) Plan * subquery_planner(Query *parse, double tuple_fraction) { + List *l; + List *rangetable = parse->rtable; + RangeTblEntry *rangeTblEntry; /* * A HAVING clause without aggregates is equivalent to a WHERE clause @@ -138,6 +141,18 @@ subquery_planner(Query *parse, double tuple_fraction) parse->qual = eval_const_expressions(parse->qual); parse->havingQual = eval_const_expressions(parse->havingQual); + /* + * If the query is going to look for subclasses, but no subclasses + * actually exist, then we can optimise away the union that would + * otherwise happen and thus save some time. + */ + foreach(l, rangetable) + { + rangeTblEntry = (RangeTblEntry *)lfirst(l); + if (rangeTblEntry->inh && !has_subclass(rangeTblEntry->relid)) + rangeTblEntry->inh = FALSE; + } + /* * Canonicalize the qual, and convert it to implicit-AND format. * diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 34f687809f1..42a2fb416a7 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,11 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.53 2000/05/30 04:24:48 tgl Exp $ +<<<<<<< plancat.c + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.54 2000/06/09 01:44:16 momjian Exp $ +======= + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.54 2000/06/09 01:44:16 momjian Exp $ +>>>>>>> 1.53 * *------------------------------------------------------------------------- */ @@ -278,6 +282,25 @@ find_inheritance_children(Oid inhparent) return list; } +/* + * has_subclass - + * In the current implementation, has_subclass returns whether a + * particular class *might* have a subclass. It will not return the + * correct result if a class had a subclass which was later dropped. + * This is because relhassubclass in pg_class is not updated, + * possibly because of efficiency and/or concurrency concerns. + * Currently has_subclass is only used as an efficiency hack, so this + * is ok. + */ +bool has_subclass(Oid relationId) +{ + HeapTuple tuple = + SearchSysCacheTuple(RELOID, + ObjectIdGetDatum(relationId), + 0, 0, 0); + return ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass; +} + #ifdef NOT_USED /* * VersionGetParents diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 5eef60918cc..5de51410fe8 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: analyze.c,v 1.145 2000/05/30 00:49:50 momjian Exp $ + * $Id: analyze.c,v 1.146 2000/06/09 01:44:18 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -270,7 +270,7 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt) /* set up a range table */ makeRangeTable(pstate, NULL); - setTargetTable(pstate, stmt->relname); + setTargetTable(pstate, stmt->relname, stmt->inh); qry->distinctClause = NIL; @@ -368,7 +368,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) * (We didn't want it there until now since it shouldn't be visible in * the SELECT part.) */ - setTargetTable(pstate, stmt->relname); + setTargetTable(pstate, stmt->relname, FALSE); /* now the range table will not change */ qry->rtable = pstate->p_rtable; @@ -1489,7 +1489,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt) * do this with REPLACE in POSTQUEL so we keep the feature. */ makeRangeTable(pstate, stmt->fromClause); - setTargetTable(pstate, stmt->relname); + setTargetTable(pstate, stmt->relname, stmt->inh); qry->targetList = transformTargetList(pstate, stmt->targetList); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index d19edf96947..38539964f5b 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.169 2000/05/31 00:28:24 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.170 2000/06/09 01:44:18 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -49,6 +49,7 @@ #include "storage/lmgr.h" #include "utils/acl.h" #include "utils/numeric.h" +#include "commands/variable.h" #ifdef MULTIBYTE #include "miscadmin.h" @@ -170,7 +171,7 @@ static void doNegateFloat(Value *v); %type <list> stmtblock, stmtmulti, result, OptTempTableName, relation_name_list, OptTableElementList, - OptInherit, definition, opt_distinct, + OptUnder, OptInherit, definition, opt_distinct, opt_with, func_args, func_args_list, func_as, oper_argtypes, RuleActionList, RuleActionMulti, opt_column_list, columnList, opt_va_list, va_list, @@ -207,7 +208,7 @@ static void doNegateFloat(Value *v); %type <list> substr_list, substr_from, substr_for, trim_list %type <list> opt_interval -%type <boolean> opt_inh_star, opt_binary, opt_using, opt_instead, +%type <boolean> opt_inh_star, opt_binary, opt_using, opt_instead, opt_only opt_with_copy, index_opt_unique, opt_verbose, opt_analyze %type <boolean> opt_cursor @@ -323,7 +324,8 @@ static void doNegateFloat(Value *v); IMMEDIATE, INITIALLY, PENDANT, RESTRICT, - TRIGGER, + TRIGGER, + UNDER, OFF /* Keywords (in SQL92 non-reserved words) */ @@ -882,7 +884,7 @@ AlterTableStmt: AlterTableStmt *n = makeNode(AlterTableStmt); n->subtype = 'A'; n->relname = $3; - n->inh = $4; + n->inh = $4 || examine_subclass; n->def = $7; $$ = (Node *)n; } @@ -892,7 +894,7 @@ AlterTableStmt: AlterTableStmt *n = makeNode(AlterTableStmt); n->subtype = 'T'; n->relname = $3; - n->inh = $4; + n->inh = $4 || examine_subclass; n->name = $7; n->def = $8; $$ = (Node *)n; @@ -903,7 +905,7 @@ AlterTableStmt: AlterTableStmt *n = makeNode(AlterTableStmt); n->subtype = 'D'; n->relname = $3; - n->inh = $4; + n->inh = $4 || examine_subclass; n->name = $7; n->behavior = $8; $$ = (Node *)n; @@ -914,7 +916,7 @@ AlterTableStmt: AlterTableStmt *n = makeNode(AlterTableStmt); n->subtype = 'C'; n->relname = $3; - n->inh = $4; + n->inh = $4 || examine_subclass; n->def = $6; $$ = (Node *)n; } @@ -924,7 +926,7 @@ AlterTableStmt: AlterTableStmt *n = makeNode(AlterTableStmt); n->subtype = 'X'; n->relname = $3; - n->inh = $4; + n->inh = $4 || examine_subclass; n->name = $7; n->behavior = $8; $$ = (Node *)n; @@ -1036,14 +1038,22 @@ copy_null: WITH NULL_P AS Sconst { $$ = $4; } * *****************************************************************************/ -CreateStmt: CREATE OptTemp TABLE relation_name '(' OptTableElementList ')' - OptInherit +CreateStmt: CREATE OptTemp TABLE relation_name OptUnder '(' OptTableElementList ')' OptInherit { CreateStmt *n = makeNode(CreateStmt); n->istemp = $2; n->relname = $4; - n->tableElts = $6; - n->inhRelnames = $8; + n->tableElts = $7; + n->inhRelnames = nconc($5, $9); +/* if ($5 != NIL) + { + n->inhRelnames = $5; + } + else + { */ + /* INHERITS is deprecated */ + /* n->inhRelnames = $9; + } */ n->constraints = NIL; $$ = (Node *)n; } @@ -1400,8 +1410,17 @@ key_reference: NO ACTION { $$ = FKCONSTR_ON_KEY_NOACTION; } | SET DEFAULT { $$ = FKCONSTR_ON_KEY_SETDEFAULT; } ; +OptUnder: UNDER relation_name_list { $$ = $2; } + | /*EMPTY*/ { $$ = NIL; } + ; + +opt_only: ONLY { $$ = FALSE; } + | /*EMPTY*/ { $$ = TRUE; } + ; + +/* INHERITS is Deprecated */ OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; } - | /*EMPTY*/ { $$ = NIL; } + | /*EMPTY*/ { $$ = NIL; } ; /* @@ -1409,11 +1428,13 @@ OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; } * SELECT ... INTO. */ -CreateAsStmt: CREATE OptTemp TABLE relation_name OptCreateAs AS SelectStmt +CreateAsStmt: CREATE OptTemp TABLE relation_name OptUnder OptCreateAs AS SelectStmt { - SelectStmt *n = (SelectStmt *)$7; - if ($5 != NIL) - mapTargetColumns($5, n->targetList); + SelectStmt *n = (SelectStmt *)$8; + if ($5 != NIL) + yyerror("CREATE TABLE/AS SELECT does not support UNDER"); + if ($6 != NIL) + mapTargetColumns($6, n->targetList); if (n->into != NULL) elog(ERROR,"CREATE TABLE/AS SELECT may not specify INTO"); n->istemp = $2; @@ -2536,11 +2557,12 @@ opt_force: FORCE { $$ = TRUE; } *****************************************************************************/ RenameStmt: ALTER TABLE relation_name opt_inh_star + /* "*" deprecated */ RENAME opt_column opt_name TO name { RenameStmt *n = makeNode(RenameStmt); n->relname = $3; - n->inh = $4; + n->inh = $4 || examine_subclass; n->column = $7; n->newname = $9; $$ = (Node *)n; @@ -3094,12 +3116,12 @@ columnElem: ColId opt_indirection * *****************************************************************************/ -DeleteStmt: DELETE FROM relation_name - where_clause +DeleteStmt: DELETE FROM opt_only relation_name where_clause { DeleteStmt *n = makeNode(DeleteStmt); - n->relname = $3; - n->whereClause = $4; + n->inh = $3; + n->relname = $4; + n->whereClause = $5; $$ = (Node *)n; } ; @@ -3136,16 +3158,17 @@ opt_lmode: SHARE { $$ = TRUE; } * *****************************************************************************/ -UpdateStmt: UPDATE relation_name +UpdateStmt: UPDATE opt_only relation_name SET update_target_list from_clause where_clause { UpdateStmt *n = makeNode(UpdateStmt); - n->relname = $2; - n->targetList = $4; - n->fromClause = $5; - n->whereClause = $6; + n->inh = $2; + n->relname = $3; + n->targetList = $5; + n->fromClause = $6; + n->whereClause = $7; $$ = (Node *)n; } ; @@ -3780,10 +3803,10 @@ where_clause: WHERE a_expr { $$ = $2; } relation_expr: relation_name { - /* normal relations */ + /* default inheritance */ $$ = makeNode(RelExpr); $$->relname = $1; - $$->inh = FALSE; + $$->inh = examine_subclass; } | relation_name '*' %prec '=' { @@ -3792,6 +3815,14 @@ relation_expr: relation_name $$->relname = $1; $$->inh = TRUE; } + | ONLY relation_name %prec '=' + { + /* no inheritance */ + $$ = makeNode(RelExpr); + $$->relname = $2; + $$->inh = FALSE; + } + ; opt_array_bounds: '[' ']' opt_array_bounds { $$ = lcons(makeInteger(-1), $3); } @@ -5396,7 +5427,6 @@ TokenId: ABSOLUTE { $$ = "absolute"; } | NOTIFY { $$ = "notify"; } | OF { $$ = "of"; } | OIDS { $$ = "oids"; } - | ONLY { $$ = "only"; } | OPERATOR { $$ = "operator"; } | OPTION { $$ = "option"; } | PARTIAL { $$ = "partial"; } @@ -5433,6 +5463,7 @@ TokenId: ABSOLUTE { $$ = "absolute"; } | TRIGGER { $$ = "trigger"; } | TRUNCATE { $$ = "truncate"; } | TRUSTED { $$ = "trusted"; } + | UNDER { $$ = "under"; } | UNLISTEN { $$ = "unlisten"; } | UNTIL { $$ = "until"; } | UPDATE { $$ = "update"; } @@ -5534,6 +5565,7 @@ ColLabel: ColId { $$ = $1; } | OFF { $$ = "off"; } | OFFSET { $$ = "offset"; } | ON { $$ = "on"; } + | ONLY { $$ = "only"; } | OR { $$ = "or"; } | ORDER { $$ = "order"; } | OUTER_P { $$ = "outer"; } diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index d5ebdbb0918..c6cc5ad9e93 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -8,7 +8,11 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.73 2000/05/31 00:28:24 petere Exp $ +<<<<<<< keywords.c + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.74 2000/06/09 01:44:18 momjian Exp $ +======= + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.74 2000/06/09 01:44:18 momjian Exp $ +>>>>>>> 1.73 * *------------------------------------------------------------------------- */ @@ -247,6 +251,7 @@ static ScanKeyword ScanKeywords[] = { {"truncate", TRUNCATE}, {"trusted", TRUSTED}, {"type", TYPE_P}, + {"under", UNDER}, {"union", UNION}, {"unique", UNIQUE}, {"unlisten", UNLISTEN}, diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 34f67fb4a16..53fa819d069 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.63 2000/06/08 22:37:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.64 2000/06/09 01:44:18 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -72,7 +72,7 @@ makeRangeTable(ParseState *pstate, List *frmList) * there is no other use of any of its attributes. Tricky, eh? */ void -setTargetTable(ParseState *pstate, char *relname) +setTargetTable(ParseState *pstate, char *relname, bool inh) { RangeTblEntry *rte; @@ -80,7 +80,7 @@ setTargetTable(ParseState *pstate, char *relname) if (refnameRangeTablePosn(pstate, relname, NULL) == 0) rte = addRangeTableEntry(pstate, relname, makeAttr(relname, NULL), - FALSE, FALSE, FALSE); + inh, FALSE, FALSE); else rte = refnameRangeTableEntry(pstate, relname); diff --git a/src/bin/pgaccess/lib/help/create_table.hlp b/src/bin/pgaccess/lib/help/create_table.hlp index c55548bfb01..b344edebd04 100644 --- a/src/bin/pgaccess/lib/help/create_table.hlp +++ b/src/bin/pgaccess/lib/help/create_table.hlp @@ -9,7 +9,7 @@ CREATE \[ TEMPORARY | TEMP \] TABLE table ( \[, PRIMARY KEY ( column \[, ...\] ) \] \[, CHECK ( condition ) \] \[, table_constraint_clause \] - ) \[ INHERITS ( inherited_table \[, ...\] ) \] + ) \[ UNDER inherited_table \[, ...\] \] " {code} " TEMPORARY The table is created only for this session, and is automatically dropped on session exit. Existing permanent tables with the same name are not visible while the temporary table exists. diff --git a/src/bin/pgaccess/lib/help/inheritance.hlp b/src/bin/pgaccess/lib/help/inheritance.hlp index b402c30fdf5..15e15cd744f 100644 --- a/src/bin/pgaccess/lib/help/inheritance.hlp +++ b/src/bin/pgaccess/lib/help/inheritance.hlp @@ -11,7 +11,7 @@ Let's create two classes. The capitals class contains state capitals which are a CREATE TABLE capitals ( state char2 - ) INHERITS (cities); + ) UNDER cities; " {code} " In this case, an instance of capitals inherits all attributes (name, population, and altitude) from its parent, cities. The type of the attribute name is text, a native Postgres type for variable length ASCII strings. The type of the attribute population is float, a native Postgres type for double precision floating point numbers. State capitals have an extra attribute, state, that shows their state. In Postgres, a class can inherit from zero or more other classes, and a query can reference either all instances of a class or all instances of a class plus all of its descendants. diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index d3d870a4116..eb731c955d4 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_attribute.h,v 1.56 2000/05/28 17:56:16 tgl Exp $ + * $Id: pg_attribute.h,v 1.57 2000/06/09 01:44:22 momjian Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -429,7 +429,8 @@ DATA(insert OID = 0 ( 1249 cmax 29 0 4 -6 0 -1 -1 t p f i f f)); { 1259, {"relrefs"}, 21, 0, 2, 16, 0, -1, -1, '\001', 'p', '\0', 's', '\0', '\0' }, \ { 1259, {"relhaspkey"}, 16, 0, 1, 17, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ { 1259, {"relhasrules"}, 16, 0, 1, 18, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ -{ 1259, {"relacl"}, 1034, 0, -1, 19, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' } +{ 1259, {"relhassubclass"},16, 0, 1, 19, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ +{ 1259, {"relacl"}, 1034, 0, -1, 20, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' } DATA(insert OID = 0 ( 1259 relname 19 0 NAMEDATALEN 1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1259 reltype 26 0 4 2 0 -1 -1 t p f i f f)); @@ -449,7 +450,8 @@ DATA(insert OID = 0 ( 1259 relfkeys 21 0 2 15 0 -1 -1 t p f s f f)); DATA(insert OID = 0 ( 1259 relrefs 21 0 2 16 0 -1 -1 t p f s f f)); DATA(insert OID = 0 ( 1259 relhaspkey 16 0 1 17 0 -1 -1 t p f c f f)); DATA(insert OID = 0 ( 1259 relhasrules 16 0 1 18 0 -1 -1 t p f c f f)); -DATA(insert OID = 0 ( 1259 relacl 1034 0 -1 19 0 -1 -1 f p f i f f)); +DATA(insert OID = 0 ( 1259 relhassubclass 16 0 1 19 0 -1 -1 t p f c f f)); +DATA(insert OID = 0 ( 1259 relacl 1034 0 -1 20 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1259 ctid 27 0 6 -1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1259 oid 26 0 4 -2 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1259 xmin 28 0 4 -3 0 -1 -1 t p f i f f)); diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index 15c9e9fcd92..25dd55eacb3 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_class.h,v 1.34 2000/05/28 17:56:16 tgl Exp $ + * $Id: pg_class.h,v 1.35 2000/06/09 01:44:23 momjian Exp $ * * NOTES * ``pg_relation'' is being replaced by ``pg_class''. currently @@ -78,11 +78,12 @@ CATALOG(pg_class) BOOTSTRAP int2 relrefs; /* # of references to this relation */ bool relhaspkey; /* has PRIMARY KEY */ bool relhasrules; + bool relhassubclass; aclitem relacl[1]; /* this is here for the catalog */ } FormData_pg_class; #define CLASS_TUPLE_SIZE \ - (offsetof(FormData_pg_class,relhasrules) + sizeof(bool)) + (offsetof(FormData_pg_class,relhassubclass) + sizeof(bool)) /* ---------------- * Form_pg_class corresponds to a pointer to a tuple with @@ -102,8 +103,8 @@ typedef FormData_pg_class *Form_pg_class; * relacl field. * ---------------- */ -#define Natts_pg_class_fixed 18 -#define Natts_pg_class 19 +#define Natts_pg_class_fixed 19 +#define Natts_pg_class 20 #define Anum_pg_class_relname 1 #define Anum_pg_class_reltype 2 #define Anum_pg_class_relowner 3 @@ -122,38 +123,39 @@ typedef FormData_pg_class *Form_pg_class; #define Anum_pg_class_relrefs 16 #define Anum_pg_class_relhaspkey 17 #define Anum_pg_class_relhasrules 18 -#define Anum_pg_class_relacl 19 +#define Anum_pg_class_relhassubclass 19 +#define Anum_pg_class_relacl 20 /* ---------------- * initial contents of pg_class * ---------------- */ -DATA(insert OID = 1247 ( pg_type 71 PGUID 0 0 0 0 f f r 16 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1247 ( pg_type 71 PGUID 0 0 0 0 f f r 16 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 0 0 0 f f r 15 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 0 0 0 f f r 15 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1255 ( pg_proc 81 PGUID 0 0 0 0 f f r 17 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1255 ( pg_proc 81 PGUID 0 0 0 0 f f r 17 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1259 ( pg_class 83 PGUID 0 0 0 0 f f r 19 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1259 ( pg_class 83 PGUID 0 0 0 0 f f r 20 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1260 ( pg_shadow 86 PGUID 0 0 0 0 f t r 8 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1260 ( pg_shadow 86 PGUID 0 0 0 0 f t r 8 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1261 ( pg_group 87 PGUID 0 0 0 0 f t r 3 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1261 ( pg_group 87 PGUID 0 0 0 0 f t r 3 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1262 ( pg_database 88 PGUID 0 0 0 0 f t r 4 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1262 ( pg_database 88 PGUID 0 0 0 0 f t r 4 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1264 ( pg_variable 90 PGUID 0 0 0 0 f t s 1 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1264 ( pg_variable 90 PGUID 0 0 0 0 f t s 1 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1269 ( pg_log 99 PGUID 0 0 0 0 f t s 1 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1269 ( pg_log 99 PGUID 0 0 0 0 f t s 1 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 376 ( pg_xactlock 0 PGUID 0 0 0 0 f t s 1 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 376 ( pg_xactlock 0 PGUID 0 0 0 0 f t s 1 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1215 ( pg_attrdef 109 PGUID 0 0 0 0 t t r 4 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1215 ( pg_attrdef 109 PGUID 0 0 0 0 t t r 4 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1216 ( pg_relcheck 110 PGUID 0 0 0 0 t t r 4 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1216 ( pg_relcheck 110 PGUID 0 0 0 0 t t r 4 0 0 0 0 0 f f f _null_ )); DESCR(""); -DATA(insert OID = 1219 ( pg_trigger 111 PGUID 0 0 0 0 t t r 13 0 0 0 0 0 f f _null_ )); +DATA(insert OID = 1219 ( pg_trigger 111 PGUID 0 0 0 0 t t r 13 0 0 0 0 0 f f f _null_ )); DESCR(""); #define RelOid_pg_type 1247 diff --git a/src/include/commands/variable.h b/src/include/commands/variable.h index 682d84e3ca8..de26bcd6e04 100644 --- a/src/include/commands/variable.h +++ b/src/include/commands/variable.h @@ -2,7 +2,7 @@ * Headers for handling of 'SET var TO', 'SHOW var' and 'RESET var' * statements * - * $Id: variable.h,v 1.10 2000/05/31 00:28:37 petere Exp $ + * $Id: variable.h,v 1.11 2000/06/09 01:44:24 momjian Exp $ * */ #ifndef VARIABLE_H @@ -13,5 +13,6 @@ extern void GetPGVariable(const char *name); extern void ResetPGVariable(const char *name); extern void set_default_datestyle(void); +extern bool examine_subclass; #endif /* VARIABLE_H */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 54c57688329..c4fae8b0450 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.105 2000/05/28 20:34:49 tgl Exp $ + * $Id: parsenodes.h,v 1.106 2000/06/09 01:44:26 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -795,6 +795,7 @@ typedef struct DeleteStmt NodeTag type; char *relname; /* relation to delete from */ Node *whereClause; /* qualifications */ + bool inh; /* delete from subclasses */ } DeleteStmt; /* ---------------------- @@ -808,6 +809,7 @@ typedef struct UpdateStmt List *targetList; /* the target list (of ResTarget) */ Node *whereClause; /* qualifications */ List *fromClause; /* the from clause */ + bool inh; /* update subclasses */ } UpdateStmt; /* ---------------------- diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h index c68f0659fa1..a0e9881dc87 100644 --- a/src/include/nodes/pg_list.h +++ b/src/include/nodes/pg_list.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_list.h,v 1.17 2000/04/12 17:16:40 momjian Exp $ + * $Id: pg_list.h,v 1.18 2000/06/09 01:44:26 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -118,6 +118,7 @@ extern void set_nth(List *l, int n, void *elem); extern List *set_difference(List *list1, List *list2); extern List *set_differencei(List *list1, List *list2); +extern List *lreverse(List *l); extern List *LispUnion(List *list1, List *list2); extern List *LispUnioni(List *list1, List *list2); diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h index dc665530f8c..b9a868d4420 100644 --- a/src/include/parser/parse_clause.h +++ b/src/include/parser/parse_clause.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_clause.h,v 1.17 2000/04/12 17:16:45 momjian Exp $ + * $Id: parse_clause.h,v 1.18 2000/06/09 01:44:29 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -17,7 +17,7 @@ #include "parser/parse_node.h" extern void makeRangeTable(ParseState *pstate, List *frmList); -extern void setTargetTable(ParseState *pstate, char *relname); +extern void setTargetTable(ParseState *pstate, char *relname, bool inh); extern Node *transformWhereClause(ParseState *pstate, Node *where); extern List *transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist); diff --git a/src/interfaces/ecpg/preproc/keywords.c b/src/interfaces/ecpg/preproc/keywords.c index cadaffbefc1..75676d00e90 100644 --- a/src/interfaces/ecpg/preproc/keywords.c +++ b/src/interfaces/ecpg/preproc/keywords.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.26 2000/04/08 12:20:27 meskes Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.27 2000/06/09 01:44:31 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -246,6 +246,7 @@ static ScanKeyword ScanKeywords[] = { {"truncate", TRUNCATE}, {"trusted", TRUSTED}, {"type", TYPE_P}, + {"under", UNDER}, {"union", UNION}, {"unique", UNIQUE}, {"unlisten", UNLISTEN}, diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 96579ecc539..b09aa80c6c4 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -236,7 +236,7 @@ make_name(void) REINDEX, RENAME, RESET, RETURNS, ROW, RULE, SEQUENCE, SERIAL, SETOF, SHARE, SHOW, START, STATEMENT, STDIN, STDOUT, SYSID TEMP, TRUNCATE, TRUSTED, - UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION + UNDER, UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION /* Special keywords, not in the query language - see the "lex" file */ %token <str> IDENT SCONST Op CSTRING CVARIABLE CPP_LINE @@ -276,7 +276,7 @@ make_name(void) %type <str> Iconst Fconst Sconst TransactionStmt CreateStmt UserId %type <str> CreateAsElement OptCreateAs CreateAsList CreateAsStmt -%type <str> OptInherit key_reference comment_text ConstraintDeferrabilitySpec +%type <str> OptUnder key_reference comment_text ConstraintDeferrabilitySpec %type <str> key_match ColLabel SpecialRuleRelation ColId columnDef %type <str> ColConstraint ColConstraintElem NumericOnly FloatOnly %type <str> OptTableElementList OptTableElement TableConstraint @@ -995,7 +995,7 @@ copy_null: WITH NULL_P AS Sconst { $$ = cat2_str(make_str("with null as"), $4); *****************************************************************************/ CreateStmt: CREATE OptTemp TABLE relation_name '(' OptTableElementList ')' - OptInherit + OptUnder { $$ = cat_str(8, make_str("create"), $2, make_str("table"), $4, make_str("("), $6, make_str(")"), $8); } @@ -1192,7 +1192,8 @@ key_reference: NO ACTION { $$ = make_str("no action"); } | SET NULL_P { $$ = make_str("set null"); } ; -OptInherit: INHERITS '(' relation_name_list ')' { $$ = cat_str(3, make_str("inherits ("), $3, make_str(")")); } +OptUnder: UNDER relation_name_list { $$ = cat_str(2, make_str("under "), $2); } + | INHERITS '(' relation_name_list ')' { $$ = cat_str(3, make_str("inherits ("), $3, make_str(")")); } | /*EMPTY*/ { $$ = EMPTY; } ; @@ -2877,6 +2878,11 @@ relation_expr: relation_name /* inheritance query */ $$ = cat2_str($1, make_str("*")); } + | ONLY relation_name %prec '=' + { + /* inheritance query */ + $$ = cat2_str(make_str("ONLY "), $2); + } opt_array_bounds: '[' ']' opt_array_bounds { @@ -5081,6 +5087,7 @@ TokenId: ABSOLUTE { $$ = make_str("absolute"); } | TRIGGER { $$ = make_str("trigger"); } | TRUNCATE { $$ = make_str("truncate"); } | TRUSTED { $$ = make_str("trusted"); } + | UNDER { $$ = make_str("under"); } | UNLISTEN { $$ = make_str("unlisten"); } | UNTIL { $$ = make_str("until"); } | UPDATE { $$ = make_str("update"); } diff --git a/src/test/regress/sql/run_check.tests b/src/test/regress/sql/run_check.tests index 8c832e016c4..b3caf933f05 100644 --- a/src/test/regress/sql/run_check.tests +++ b/src/test/regress/sql/run_check.tests @@ -70,6 +70,7 @@ parallel group3 test create_aggregate test create_operator test create_index + test inherit endparallel test create_view # Depends on the above |