diff options
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}, |