<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.140 2002/07/12 18:43:12 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.141 2002/07/16 22:12:18 tgl Exp $
-->
<appendix id="release">
worries about funny characters.
-->
<literallayout><![CDATA[
+Sequences created by SERIAL column definitions now auto-drop with the column
Most forms of DROP now support RESTRICT and CASCADE options
Recursive SQL functions can be defined
User-defined procedural languages can register a validator function to check new functions as they are created
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.208 2002/07/16 05:53:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.209 2002/07/16 22:12:18 tgl Exp $
*
*
* INTERFACE ROUTINES
static FormData_pg_attribute a1 = {
0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
SelfItemPointerAttributeNumber, 0, -1, -1,
- false, 'p', false, 'i', false, false
+ false, 'p', false, 'i', true, false
};
static FormData_pg_attribute a2 = {
0, {"oid"}, OIDOID, 0, sizeof(Oid),
ObjectIdAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', false, false
+ true, 'p', false, 'i', true, false
};
static FormData_pg_attribute a3 = {
0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
MinTransactionIdAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', false, false
+ true, 'p', false, 'i', true, false
};
static FormData_pg_attribute a4 = {
0, {"cmin"}, CIDOID, 0, sizeof(CommandId),
MinCommandIdAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', false, false
+ true, 'p', false, 'i', true, false
};
static FormData_pg_attribute a5 = {
0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
MaxTransactionIdAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', false, false
+ true, 'p', false, 'i', true, false
};
static FormData_pg_attribute a6 = {
0, {"cmax"}, CIDOID, 0, sizeof(CommandId),
MaxCommandIdAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', false, false
+ true, 'p', false, 'i', true, false
};
/*
static FormData_pg_attribute a7 = {
0, {"tableoid"}, OIDOID, 0, sizeof(Oid),
TableOidAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', false, false
+ true, 'p', false, 'i', true, false
};
static Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
bool hasindex;
Relation idescs[Num_pg_attr_indices];
int natts = tupdesc->natts;
+ ObjectAddress myself,
+ referenced;
/*
* open pg_attribute
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
/*
- * first we add the user attributes..
+ * First we add the user attributes. This is also a convenient place
+ * to add dependencies on their datatypes.
*/
dpp = tupdesc->attrs;
for (i = 0; i < natts; i++)
CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
heap_freetuple(tup);
+
+ myself.classId = RelOid_pg_class;
+ myself.objectId = new_rel_oid;
+ myself.objectSubId = i+1;
+ referenced.classId = RelOid_pg_type;
+ referenced.objectId = (*dpp)->atttypid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
dpp++;
}
/*
- * next we add the system attributes. Skip OID if rel has no OIDs.
+ * Next we add the system attributes. Skip OID if rel has no OIDs.
+ * Skip all for a view. We don't bother with making datatype
+ * dependencies here, since presumably all these types are pinned.
*/
if (relkind != RELKIND_VIEW)
{
}
/*
- * close pg_attribute indices
+ * clean up
*/
if (hasindex)
CatalogCloseIndices(Num_pg_attr_indices, idescs);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.49 2002/06/20 20:29:26 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.50 2002/07/16 22:12:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "access/heapam.h"
#include "catalog/catname.h"
+#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_aggregate.h"
Oid procOid;
TupleDesc tupDesc;
int i;
+ ObjectAddress myself,
+ referenced;
/* sanity checks */
if (!aggName)
}
heap_close(aggdesc, RowExclusiveLock);
+
+ /*
+ * Create dependencies for the aggregate (above and beyond those
+ * already made by ProcedureCreate). Note: we don't need an explicit
+ * dependency on aggTransType since we depend on it indirectly through
+ * transfn.
+ */
+ myself.classId = RelOid_pg_proc;
+ myself.objectId = procOid;
+ myself.objectSubId = 0;
+
+ /* Depends on transition function */
+ referenced.classId = RelOid_pg_proc;
+ referenced.objectId = transfn;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* Depends on final function, if any */
+ if (OidIsValid(finalfn))
+ {
+ referenced.classId = RelOid_pg_proc;
+ referenced.objectId = finalfn;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.2 2002/07/16 05:53:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.3 2002/07/16 22:12:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (OidIsValid(foreignRelId))
{
/*
- * Register dependency from constraint to foreign relation,
+ * Register normal dependency from constraint to foreign relation,
* or to specific column(s) if any are mentioned.
- *
- * In normal case of two separate relations, make this a NORMAL
- * dependency (so dropping the FK table would require CASCADE).
- * However, for a self-reference just make it AUTO.
*/
- DependencyType deptype;
ObjectAddress relobject;
- deptype = (foreignRelId == relId) ? DEPENDENCY_AUTO : DEPENDENCY_NORMAL;
relobject.classId = RelOid_pg_class;
relobject.objectId = foreignRelId;
if (foreignNKeys > 0)
{
relobject.objectSubId = foreignKey[i];
- recordDependencyOn(&conobject, &relobject, deptype);
+ recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
}
}
else
{
relobject.objectSubId = 0;
- recordDependencyOn(&conobject, &relobject, deptype);
+ recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
}
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.2 2002/07/16 05:53:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.3 2002/07/16 22:12:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
heap_close(dependDesc, RowExclusiveLock);
}
+/*
+ * deleteDependencyRecordsFor -- delete all records with given depender
+ * classId/objectId.
+ *
+ * This is used when redefining an existing object. Links leading to the
+ * object do not change, and links leading from it will be recreated
+ * (possibly with some differences from before).
+ */
+void
+deleteDependencyRecordsFor(Oid classId, Oid objectId)
+{
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ depRel = heap_openr(DependRelationName, RowExclusiveLock);
+
+ ScanKeyEntryInitialize(&key[0], 0x0,
+ Anum_pg_depend_classid, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyEntryInitialize(&key[1], 0x0,
+ Anum_pg_depend_objid, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+
+ scan = systable_beginscan(depRel, DependDependerIndex, true,
+ SnapshotNow, 2, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ simple_heap_delete(depRel, &tup->t_self);
+ }
+
+ systable_endscan(scan);
+
+ heap_close(depRel, RowExclusiveLock);
+}
/*
* isObjectPinned()
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.70 2002/06/20 20:29:26 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.71 2002/07/16 22:12:18 tgl Exp $
*
* NOTES
* these routines moved here from commands/define.c and somewhat cleaned up.
#include "access/heapam.h"
#include "catalog/catname.h"
+#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_operator.h"
Oid leftTypeId, Oid rightTypeId,
bool isCommutator);
+static void makeOperatorDependencies(HeapTuple tuple, Oid pg_operator_relid);
+
/*
* Check whether a proposed operator name is legal
CatalogCloseIndices(Num_pg_operator_indices, idescs);
}
+ /* Add dependencies for the entry */
+ makeOperatorDependencies(tup, RelationGetRelid(pg_operator_desc));
+
heap_freetuple(tup);
/*
CatalogCloseIndices(Num_pg_operator_indices, idescs);
}
+ /* Add dependencies for the entry */
+ makeOperatorDependencies(tup, RelationGetRelid(pg_operator_desc));
+
heap_close(pg_operator_desc, RowExclusiveLock);
/*
heap_close(pg_operator_desc, RowExclusiveLock);
}
+
+/*
+ * Create dependencies for a new operator (either a freshly inserted
+ * complete operator, a new shell operator, or a just-updated shell).
+ *
+ * NB: the OidIsValid tests in this routine are *all* necessary, in case
+ * the given operator is a shell.
+ */
+static void
+makeOperatorDependencies(HeapTuple tuple, Oid pg_operator_relid)
+{
+ Form_pg_operator oper = (Form_pg_operator) GETSTRUCT(tuple);
+ ObjectAddress myself,
+ referenced;
+
+ myself.classId = pg_operator_relid;
+ myself.objectId = tuple->t_data->t_oid;
+ myself.objectSubId = 0;
+
+ /* In case we are updating a shell, delete any existing entries */
+ deleteDependencyRecordsFor(myself.classId, myself.objectId);
+
+ /* Dependency on left type */
+ if (OidIsValid(oper->oprleft))
+ {
+ referenced.classId = RelOid_pg_type;
+ referenced.objectId = oper->oprleft;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Dependency on right type */
+ if (OidIsValid(oper->oprright))
+ {
+ referenced.classId = RelOid_pg_type;
+ referenced.objectId = oper->oprright;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Dependency on result type */
+ if (OidIsValid(oper->oprresult))
+ {
+ referenced.classId = RelOid_pg_type;
+ referenced.objectId = oper->oprresult;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /*
+ * NOTE: we do not consider the operator to depend on the associated
+ * operators oprcom, oprnegate, oprlsortop, oprrsortop, oprltcmpop,
+ * oprgtcmpop. We would not want to delete this operator if those
+ * go away, but only reset the link fields; which is not a function
+ * that the dependency code can presently handle. (Something could
+ * perhaps be done with objectSubId though.) For now, it's okay to
+ * let those links dangle if a referenced operator is removed.
+ */
+
+ /* Dependency on implementation function */
+ if (OidIsValid(oper->oprcode))
+ {
+ referenced.classId = RelOid_pg_proc;
+ referenced.objectId = oper->oprcode;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Dependency on restriction selectivity function */
+ if (OidIsValid(oper->oprrest))
+ {
+ referenced.classId = RelOid_pg_proc;
+ referenced.objectId = oper->oprrest;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Dependency on join selectivity function */
+ if (OidIsValid(oper->oprjoin))
+ {
+ referenced.classId = RelOid_pg_proc;
+ referenced.objectId = oper->oprjoin;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.76 2002/06/20 20:29:26 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.77 2002/07/16 22:12:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "access/heapam.h"
#include "catalog/catname.h"
+#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
NameData procname;
TupleDesc tupDesc;
Oid retval;
+ bool is_update;
+ ObjectAddress myself,
+ referenced;
/*
* sanity checks
simple_heap_update(rel, &tup->t_self, tup);
ReleaseSysCache(oldtup);
+ is_update = true;
}
else
{
tup = heap_formtuple(tupDesc, values, nulls);
simple_heap_insert(rel, tup);
+ is_update = false;
}
/* Need to update indices for either the insert or update case */
}
retval = tup->t_data->t_oid;
+
+ /*
+ * Create dependencies for the new function. If we are updating an
+ * existing function, first delete any existing pg_depend entries.
+ */
+ if (is_update)
+ deleteDependencyRecordsFor(RelOid_pg_proc, retval);
+
+ myself.classId = RelOid_pg_proc;
+ myself.objectId = retval;
+ myself.objectSubId = 0;
+
+ /* dependency on implementation language */
+ referenced.classId = get_system_catalog_relid(LanguageRelationName);
+ referenced.objectId = languageObjectId;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* dependency on return type */
+ if (OidIsValid(returnType))
+ {
+ referenced.classId = RelOid_pg_type;
+ referenced.objectId = returnType;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* dependency on input types */
+ for (i = 0; i < parameterCount; i++)
+ {
+ if (OidIsValid(typev[i]))
+ {
+ referenced.classId = RelOid_pg_type;
+ referenced.objectId = typev[i];
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+ }
+
heap_freetuple(tup);
heap_close(rel, RowExclusiveLock);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.35 2002/07/12 18:43:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.36 2002/07/16 22:12:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
HeapTuple tup;
TupleDesc tupDesc;
int i;
+ ObjectAddress myself,
+ referenced;
/*
* Check permission
NameListToString(stmt->plvalidator));
}
else
- valProcOid = 0;
+ valProcOid = InvalidOid;
/*
* Insert the new language into pg_language
CatalogCloseIndices(Num_pg_language_indices, idescs);
}
+ /*
+ * Create dependencies for language
+ */
+ myself.classId = RelationGetRelid(rel);
+ myself.objectId = tup->t_data->t_oid;
+ myself.objectSubId = 0;
+
+ /* dependency on the PL handler function */
+ referenced.classId = RelOid_pg_proc;
+ referenced.objectId = procOid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* dependency on the validator function, if any */
+ if (OidIsValid(valProcOid))
+ {
+ referenced.classId = RelOid_pg_proc;
+ referenced.objectId = valProcOid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
heap_close(rel, RowExclusiveLock);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.82 2002/06/20 20:29:27 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.83 2002/07/16 22:12:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
typnam->setof = FALSE;
typnam->arrayBounds = NIL;
typnam->typmod = -1;
+
coldef = makeNode(ColumnDef);
coldef->typename = typnam;
+ coldef->is_not_null = true;
coldef->raw_default = NULL;
coldef->cooked_default = NULL;
- coldef->is_not_null = false;
+ coldef->constraints = NIL;
+ coldef->support = NULL;
+
null[i - 1] = ' ';
switch (i)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.22 2002/07/16 05:53:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.23 2002/07/16 22:12:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* So, the transformation has to be postponed to this final step of
* CREATE TABLE.
*
+ * Another task that's conveniently done at this step is to add
+ * dependency links between columns and supporting relations (such
+ * as SERIAL sequences).
+ *
* First, scan schema to find new column defaults.
*/
rawDefaults = NIL;
foreach(listptr, schema)
{
ColumnDef *colDef = lfirst(listptr);
- RawColumnDefault *rawEnt;
attnum++;
- if (colDef->raw_default == NULL)
- continue;
- Assert(colDef->cooked_default == NULL);
+ if (colDef->raw_default != NULL)
+ {
+ RawColumnDefault *rawEnt;
- rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
- rawEnt->attnum = attnum;
- rawEnt->raw_default = colDef->raw_default;
- rawDefaults = lappend(rawDefaults, rawEnt);
+ Assert(colDef->cooked_default == NULL);
+
+ rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+ rawEnt->attnum = attnum;
+ rawEnt->raw_default = colDef->raw_default;
+ rawDefaults = lappend(rawDefaults, rawEnt);
+ }
+
+ if (colDef->support != NULL)
+ {
+ /* Create dependency for supporting relation for this column */
+ ObjectAddress colobject,
+ suppobject;
+
+ colobject.classId = RelOid_pg_class;
+ colobject.objectId = relationId;
+ colobject.objectSubId = attnum;
+ suppobject.classId = RelOid_pg_class;
+ suppobject.objectId = RangeVarGetRelid(colDef->support, false);
+ suppobject.objectSubId = 0;
+ recordDependencyOn(&suppobject, &colobject, DEPENDENCY_INTERNAL);
+ }
}
/*
def->raw_default = NULL;
def->cooked_default = NULL;
def->constraints = NIL;
+ def->support = NULL;
inhSchema = lappend(inhSchema, def);
newattno[parent_attno - 1] = ++child_attno;
}
HeapTuple typeTuple;
Form_pg_type tform;
int attndims;
+ ObjectAddress myself,
+ referenced;
/*
* Grab an exclusive lock on the target table, which we will NOT
heap_close(rel, NoLock); /* close rel but keep lock! */
/*
+ * Add datatype dependency for the new column.
+ */
+ myself.classId = RelOid_pg_class;
+ myself.objectId = myrelid;
+ myself.objectSubId = i;
+ referenced.classId = RelOid_pg_type;
+ referenced.objectId = attribute->atttypid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /*
* Make our catalog updates visible for subsequent steps.
*/
CommandCounterIncrement();
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.5 2002/07/12 18:43:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.6 2002/07/16 22:12:19 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
char typtype;
Datum datum;
bool isnull;
+ Node *defaultExpr = NULL;
char *defaultValue = NULL;
char *defaultValueBin = NULL;
bool typNotNull = false;
+ bool nullDefined = false;
Oid basetypelem;
int32 typNDims = length(stmt->typename->arrayBounds);
HeapTuple typeTup;
List *schema = stmt->constraints;
List *listptr;
Oid basetypeoid;
+ Oid domainoid;
Form_pg_type baseType;
/* Convert list of names to a name and namespace */
foreach(listptr, schema)
{
Constraint *colDef = lfirst(listptr);
- bool nullDefined = false;
- Node *expr;
ParseState *pstate;
switch (colDef->contype)
* don't want to cook or fiddle too much.
*/
case CONSTR_DEFAULT:
+ if (defaultExpr)
+ elog(ERROR, "CREATE DOMAIN has multiple DEFAULT expressions");
/* Create a dummy ParseState for transformExpr */
pstate = make_parsestate(NULL);
/*
* Cook the colDef->raw_expr into an expression.
* Note: Name is strictly for error message
*/
- expr = cookDefault(pstate, colDef->raw_expr,
- basetypeoid,
- stmt->typename->typmod,
- domainName);
+ defaultExpr = cookDefault(pstate, colDef->raw_expr,
+ basetypeoid,
+ stmt->typename->typmod,
+ domainName);
/*
* Expression must be stored as a nodeToString result,
* but we also require a valid textual representation
* (mainly to make life easier for pg_dump).
*/
- defaultValue = deparse_expression(expr,
+ defaultValue = deparse_expression(defaultExpr,
deparse_context_for(domainName,
InvalidOid),
false);
- defaultValueBin = nodeToString(expr);
+ defaultValueBin = nodeToString(defaultExpr);
break;
/*
* Find the NULL constraint.
*/
case CONSTR_NOTNULL:
- if (nullDefined) {
+ if (nullDefined)
elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
- } else {
- typNotNull = true;
- nullDefined = true;
- }
+ typNotNull = true;
+ nullDefined = true;
break;
case CONSTR_NULL:
- if (nullDefined) {
+ if (nullDefined)
elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
- } else {
- typNotNull = false;
- nullDefined = true;
- }
+ typNotNull = false;
+ nullDefined = true;
break;
case CONSTR_UNIQUE:
/*
* Have TypeCreate do all the real work.
*/
- TypeCreate(domainName, /* type name */
- domainNamespace, /* namespace */
- InvalidOid, /* preassigned type oid (none here) */
- InvalidOid, /* relation oid (n/a here) */
- internalLength, /* internal size */
- externalLength, /* external size */
- 'd', /* type-type (domain type) */
- delimiter, /* array element delimiter */
- inputProcedure, /* input procedure */
- outputProcedure, /* output procedure */
- receiveProcedure, /* receive procedure */
- sendProcedure, /* send procedure */
- basetypelem, /* element type ID */
- basetypeoid, /* base type ID */
- defaultValue, /* default type value (text) */
- defaultValueBin, /* default type value (binary) */
- byValue, /* passed by value */
- alignment, /* required alignment */
- storage, /* TOAST strategy */
- stmt->typename->typmod, /* typeMod value */
- typNDims, /* Array dimensions for base type */
- typNotNull); /* Type NOT NULL */
+ domainoid =
+ TypeCreate(domainName, /* type name */
+ domainNamespace, /* namespace */
+ InvalidOid, /* preassigned type oid (none here) */
+ InvalidOid, /* relation oid (n/a here) */
+ internalLength, /* internal size */
+ externalLength, /* external size */
+ 'd', /* type-type (domain type) */
+ delimiter, /* array element delimiter */
+ inputProcedure, /* input procedure */
+ outputProcedure, /* output procedure */
+ receiveProcedure, /* receive procedure */
+ sendProcedure, /* send procedure */
+ basetypelem, /* element type ID */
+ basetypeoid, /* base type ID */
+ defaultValue, /* default type value (text) */
+ defaultValueBin, /* default type value (binary) */
+ byValue, /* passed by value */
+ alignment, /* required alignment */
+ storage, /* TOAST strategy */
+ stmt->typename->typmod, /* typeMod value */
+ typNDims, /* Array dimensions for base type */
+ typNotNull); /* Type NOT NULL */
+
+ /*
+ * Add any dependencies needed for the default expression.
+ */
+ if (defaultExpr)
+ {
+ ObjectAddress domobject;
+
+ domobject.classId = RelOid_pg_type;
+ domobject.objectId = domainoid;
+ domobject.objectSubId = 0;
+
+ recordDependencyOnExpr(&domobject, defaultExpr, NIL,
+ DEPENDENCY_NORMAL);
+ }
/*
* Now we can clean up.
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: view.c,v 1.66 2002/07/12 18:43:16 tgl Exp $
+ * $Id: view.c,v 1.67 2002/07/16 22:12:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
def->raw_default = NULL;
def->cooked_default = NULL;
def->constraints = NIL;
+ def->support = NULL;
attrList = lappend(attrList, def);
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.193 2002/07/12 18:43:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.194 2002/07/16 22:12:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (from->cooked_default)
newnode->cooked_default = pstrdup(from->cooked_default);
Node_Copy(from, newnode, constraints);
+ Node_Copy(from, newnode, support);
return newnode;
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.140 2002/07/12 18:43:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.141 2002/07/16 22:12:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
return false;
if (!equal(a->constraints, b->constraints))
return false;
+ if (!equal(a->support, b->support))
+ return false;
return true;
}
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.162 2002/07/12 18:43:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.163 2002/07/16 22:12:19 tgl Exp $
*
* NOTES
* Every (plan) node in POSTGRES has an associated "out" routine which
_outToken(str, node->cooked_default);
appendStringInfo(str, " :constraints ");
_outNode(str, node->constraints);
+ appendStringInfo(str, " :support ");
+ _outNode(str, node->support);
}
static void
* 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.238 2002/07/12 18:43:17 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.239 2002/07/16 22:12:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
cxt->blist = lappend(cxt->blist, seqstmt);
/*
+ * Mark the ColumnDef so that during execution, an appropriate
+ * dependency will be added from the sequence to the column.
+ */
+ column->support = makeRangeVar(snamespace, sname);
+
+ /*
* Create appropriate constraints for SERIAL. We do this in full,
* rather than shortcutting, so that we will detect any
* conflicting constraints the user wrote (like a different
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.340 2002/07/14 23:38:13 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.341 2002/07/16 22:12:20 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
ColumnDef *n = makeNode(ColumnDef);
n->colname = $1;
n->typename = NULL;
+ n->is_not_null = false;
n->raw_default = NULL;
n->cooked_default = NULL;
- n->is_not_null = FALSE;
- n->constraints = NULL;
+ n->constraints = NIL;
+ n->support = NULL;
$$ = (Node *)n;
}
;
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: dependency.h,v 1.2 2002/07/16 05:53:34 tgl Exp $
+ * $Id: dependency.h,v 1.3 2002/07/16 22:12:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
int nreferenced,
DependencyType behavior);
+extern void deleteDependencyRecordsFor(Oid classId, Oid objectId);
+
#endif /* DEPENDENCY_H */
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parsenodes.h,v 1.186 2002/07/14 23:38:13 tgl Exp $
+ * $Id: parsenodes.h,v 1.187 2002/07/16 22:12:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* parsetree produced by gram.y, but transformCreateStmt will remove
* the item and set raw_default instead. CONSTR_DEFAULT items
* should not appear in any subsequent processing.
+ *
+ * The "support" field, if not null, denotes a supporting relation that
+ * should be linked by an internal dependency to the column. Currently
+ * this is only used to link a SERIAL column's sequence to the column.
*/
typedef struct ColumnDef
{
* tree) */
char *cooked_default; /* nodeToString representation */
List *constraints; /* other constraints on column */
+ RangeVar *support; /* supporting relation, if any */
} ColumnDef;
/*