mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
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>
This commit is contained in:
@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user