aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/analyze.c138
-rw-r--r--src/backend/parser/gram.y36
-rw-r--r--src/backend/parser/keywords.c5
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},