diff options
author | Bruce Momjian <bruce@momjian.us> | 2003-06-25 03:40:19 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2003-06-25 03:40:19 +0000 |
commit | c70e606a4c9ab39d730ef79faf59bdcd9e8d779f (patch) | |
tree | a1bd83b74784c8a9e7925c011e0bc8b9f776f383 /src/backend/parser | |
parent | dbca370278fd702efb504d57d2f89619f3be7091 (diff) | |
download | postgresql-c70e606a4c9ab39d730ef79faf59bdcd9e8d779f.tar.gz postgresql-c70e606a4c9ab39d730ef79faf59bdcd9e8d779f.zip |
Includes:
- LIKE <subtable> [ INCLUDING DEFAULTS | EXCLUDING DEFAULTS ]
- Quick cleanup of analyze.c function prototypes.
- New non-reserved keywords (INCLUDING, EXCLUDING, DEFAULTS), SQL 200X
Opted not to extend for check constraints at this time.
As per the definition that it's user defined columns, OIDs are NOT
inherited.
Doc and Source patches attached.
--
Rod Taylor <rbt@rbt.ca>
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/analyze.c | 138 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 36 | ||||
-rw-r--r-- | src/backend/parser/keywords.c | 5 |
3 files changed, 163 insertions, 16 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 3f4cb22cdf7..6476b09f99b 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.275 2003/06/16 02:03:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.276 2003/06/25 03:40:17 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,7 @@ #include "catalog/pg_index.h" #include "catalog/pg_type.h" #include "commands/prepare.h" +#include "miscadmin.h" #include "nodes/makefuncs.h" #include "optimizer/clauses.h" #include "optimizer/var.h" @@ -37,6 +38,7 @@ #include "parser/parse_type.h" #include "parser/parse_expr.h" #include "rewrite/rewriteManip.h" +#include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" @@ -112,13 +114,15 @@ static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt, static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt, List **extras_before, List **extras_after); static void transformColumnDefinition(ParseState *pstate, - CreateStmtContext *cxt, - ColumnDef *column); + CreateStmtContext *cxt, + ColumnDef *column); static void transformTableConstraint(ParseState *pstate, - CreateStmtContext *cxt, - Constraint *constraint); + CreateStmtContext *cxt, + Constraint *constraint); +static void transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, + InhRelation *inhrelation); static void transformIndexConstraints(ParseState *pstate, - CreateStmtContext *cxt); + CreateStmtContext *cxt); static void transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt, bool isAddConstraint); @@ -880,6 +884,11 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt, cxt.fkconstraints = lappend(cxt.fkconstraints, element); break; + case T_InhRelation: + transformInhRelation(pstate, &cxt, + (InhRelation *) element); + break; + default: elog(ERROR, "parser: unrecognized node (internal error)"); } @@ -1146,6 +1155,123 @@ transformTableConstraint(ParseState *pstate, CreateStmtContext *cxt, } } +/* + * transformInhRelation + * + * Change the LIKE <subtable> portion of a CREATE TABLE statement into the + * column definitions which recreate the user defined column portions of <subtable>. + */ +static void +transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, + InhRelation *inhRelation) +{ + AttrNumber parent_attno; + + Relation relation; + TupleDesc tupleDesc; + TupleConstr *constr; + AclResult aclresult; + + relation = heap_openrv(inhRelation->relation, AccessShareLock); + + if (relation->rd_rel->relkind != RELKIND_RELATION) + elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", + inhRelation->relation->relname); + + /* + * Check for SELECT privilages + */ + aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(), + ACL_SELECT); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, RelationGetRelationName(relation)); + + tupleDesc = RelationGetDescr(relation); + constr = tupleDesc->constr; + + /* + * Insert the inherited attributes into the cxt for the + * new table definition. + */ + for (parent_attno = 1; parent_attno <= tupleDesc->natts; + parent_attno++) + { + Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1]; + char *attributeName = NameStr(attribute->attname); + ColumnDef *def; + TypeName *typename; + + /* + * Ignore dropped columns in the parent. + */ + if (attribute->attisdropped) + continue; + + /* + * Create a new inherited column. + * + * For constraints, ONLY the NOT NULL constraint is inherited + * by the new column definition per SQL99. + */ + def = makeNode(ColumnDef); + def->colname = pstrdup(attributeName); + typename = makeNode(TypeName); + typename->typeid = attribute->atttypid; + typename->typmod = attribute->atttypmod; + def->typename = typename; + def->inhcount = 0; + def->is_local = false; + def->is_not_null = attribute->attnotnull; + def->raw_default = NULL; + def->cooked_default = NULL; + def->constraints = NIL; + def->support = NULL; + + /* + * Add to column list + */ + cxt->columns = lappend(cxt->columns, def); + + /* + * Copy default if any, and the default has been requested + */ + if (attribute->atthasdef && inhRelation->including_defaults) + { + char *this_default = NULL; + AttrDefault *attrdef; + int i; + + /* Find default in constraint structure */ + Assert(constr != NULL); + attrdef = constr->defval; + for (i = 0; i < constr->num_defval; i++) + { + if (attrdef[i].adnum == parent_attno) + { + this_default = attrdef[i].adbin; + break; + } + } + Assert(this_default != NULL); + + /* + * If default expr could contain any vars, we'd need to + * fix 'em, but it can't; so default is ready to apply to + * child. + */ + + def->cooked_default = pstrdup(this_default); + } + } + + /* + * Close the parent rel, but keep our AccessShareLock on it until + * xact commit. That will prevent someone else from deleting or + * ALTERing the parent before the child is committed. + */ + heap_close(relation, NoLock); +} + static void transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt) { diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index e4cf67eca36..9806d658889 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.418 2003/06/24 23:14:43 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.419 2003/06/25 03:40:18 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -165,6 +165,8 @@ static void doNegateFloat(Value *v); %type <boolean> opt_force opt_or_replace transaction_access_mode opt_grant_grant_option opt_revoke_grant_option +%type <boolean> like_including_defaults + %type <list> user_list %type <list> OptGroupList @@ -336,11 +338,11 @@ static void doNegateFloat(Value *v); CREATEUSER CROSS CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE - DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT + DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DESC DISTINCT DO DOMAIN_P DOUBLE_P DROP - EACH ELSE ENCODING ENCRYPTED END_P ESCAPE EXCEPT + EACH ELSE ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD @@ -350,7 +352,7 @@ static void doNegateFloat(Value *v); HANDLER HAVING HOLD HOUR_P - ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCREMENT + ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT INDEX INHERITS INITIALLY INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION @@ -1642,18 +1644,31 @@ ConstraintAttr: ; -/* SQL99 supports wholesale borrowing of a table definition via the LIKE clause. +/* + * SQL99 supports wholesale borrowing of a table definition via the LIKE clause. * This seems to be a poor man's inheritance capability, with the resulting * tables completely decoupled except for the original commonality in definitions. - * Seems to have much in common with CREATE TABLE AS. - thomas 2002-06-19 + * + * This is very similar to CREATE TABLE AS except for the INCLUDING DEFAULTS extension + * which is a part of SQL 200N */ -TableLikeClause: LIKE any_name +TableLikeClause: + LIKE qualified_name like_including_defaults { - elog(ERROR, "LIKE in table definitions not yet supported"); - $$ = NULL; + InhRelation *n = makeNode(InhRelation); + n->relation = $2; + n->including_defaults = $3; + + $$ = (Node *)n; } ; +like_including_defaults: + INCLUDING DEFAULTS { $$ = true; } + | EXCLUDING DEFAULTS { $$ = false; } + | /* EMPTY */ { $$ = false; } + ; + /* ConstraintElem specifies constraint syntax which is not embedded into * a column definition. ColConstraintElem specifies the embedded form. @@ -7230,6 +7245,7 @@ unreserved_keyword: | DAY_P | DEALLOCATE | DECLARE + | DEFAULTS | DEFERRED | DEFINER | DELETE_P @@ -7242,6 +7258,7 @@ unreserved_keyword: | ENCODING | ENCRYPTED | ESCAPE + | EXCLUDING | EXCLUSIVE | EXECUTE | EXPLAIN @@ -7258,6 +7275,7 @@ unreserved_keyword: | IMMEDIATE | IMMUTABLE | IMPLICIT_P + | INCLUDING | INCREMENT | INDEX | INHERITS diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index b035a828f32..ea7a3252485 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.139 2003/05/15 16:35:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.140 2003/06/25 03:40:18 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -102,6 +102,7 @@ static const ScanKeyword ScanKeywords[] = { {"decimal", DECIMAL_P}, {"declare", DECLARE}, {"default", DEFAULT}, + {"defaults", DEFAULTS}, {"deferrable", DEFERRABLE}, {"deferred", DEFERRED}, {"definer", DEFINER}, @@ -121,6 +122,7 @@ static const ScanKeyword ScanKeywords[] = { {"end", END_P}, {"escape", ESCAPE}, {"except", EXCEPT}, + {"excluding", EXCLUDING}, {"exclusive", EXCLUSIVE}, {"execute", EXECUTE}, {"exists", EXISTS}, @@ -151,6 +153,7 @@ static const ScanKeyword ScanKeywords[] = { {"immutable", IMMUTABLE}, {"implicit", IMPLICIT_P}, {"in", IN_P}, + {"including", INCLUDING}, {"increment", INCREMENT}, {"index", INDEX}, {"inherits", INHERITS}, |