mirror of
https://github.com/postgres/postgres.git
synced 2025-11-22 12:22:45 +03:00
Identity columns
This is the SQL standard-conforming variant of PostgreSQL's serial columns. It fixes a few usability issues that serial columns have: - CREATE TABLE / LIKE copies default but refers to same sequence - cannot add/drop serialness with ALTER TABLE - dropping default does not drop sequence - need to grant separate privileges to sequence - other slight weirdnesses because serial is some kind of special macro Reviewed-by: Vitaly Burovoy <vitaly.burovoy@gmail.com>
This commit is contained in:
@@ -488,7 +488,7 @@ getExtensionOfObject(Oid classId, Oid objectId)
|
||||
/*
|
||||
* Detect whether a sequence is marked as "owned" by a column
|
||||
*
|
||||
* An ownership marker is an AUTO dependency from the sequence to the
|
||||
* An ownership marker is an AUTO or INTERNAL dependency from the sequence to the
|
||||
* column. If we find one, store the identity of the owning column
|
||||
* into *tableId and *colId and return TRUE; else return FALSE.
|
||||
*
|
||||
@@ -497,7 +497,7 @@ getExtensionOfObject(Oid classId, Oid objectId)
|
||||
* not happen, though.
|
||||
*/
|
||||
bool
|
||||
sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
|
||||
sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
|
||||
{
|
||||
bool ret = false;
|
||||
Relation depRel;
|
||||
@@ -524,7 +524,7 @@ sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
|
||||
Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
|
||||
|
||||
if (depform->refclassid == RelationRelationId &&
|
||||
depform->deptype == DEPENDENCY_AUTO)
|
||||
depform->deptype == deptype)
|
||||
{
|
||||
*tableId = depform->refobjid;
|
||||
*colId = depform->refobjsubid;
|
||||
@@ -541,27 +541,15 @@ sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove any existing "owned" markers for the specified sequence.
|
||||
*
|
||||
* Note: we don't provide a special function to install an "owned"
|
||||
* marker; just use recordDependencyOn().
|
||||
*/
|
||||
void
|
||||
markSequenceUnowned(Oid seqId)
|
||||
{
|
||||
deleteDependencyRecordsForClass(RelationRelationId, seqId,
|
||||
RelationRelationId, DEPENDENCY_AUTO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Collect a list of OIDs of all sequences owned by the specified relation.
|
||||
* Collect a list of OIDs of all sequences owned by the specified relation,
|
||||
* and column if specified.
|
||||
*/
|
||||
List *
|
||||
getOwnedSequences(Oid relid)
|
||||
getOwnedSequences(Oid relid, AttrNumber attnum)
|
||||
{
|
||||
List *result = NIL;
|
||||
Relation depRel;
|
||||
ScanKeyData key[2];
|
||||
ScanKeyData key[3];
|
||||
SysScanDesc scan;
|
||||
HeapTuple tup;
|
||||
|
||||
@@ -575,23 +563,28 @@ getOwnedSequences(Oid relid)
|
||||
Anum_pg_depend_refobjid,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(relid));
|
||||
if (attnum)
|
||||
ScanKeyInit(&key[2],
|
||||
Anum_pg_depend_refobjsubid,
|
||||
BTEqualStrategyNumber, F_INT4EQ,
|
||||
Int32GetDatum(attnum));
|
||||
|
||||
scan = systable_beginscan(depRel, DependReferenceIndexId, true,
|
||||
NULL, 2, key);
|
||||
NULL, attnum ? 3 : 2, key);
|
||||
|
||||
while (HeapTupleIsValid(tup = systable_getnext(scan)))
|
||||
{
|
||||
Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
|
||||
|
||||
/*
|
||||
* We assume any auto dependency of a sequence on a column must be
|
||||
* We assume any auto or internal dependency of a sequence on a column must be
|
||||
* what we are looking for. (We need the relkind test because indexes
|
||||
* can also have auto dependencies on columns.)
|
||||
*/
|
||||
if (deprec->classid == RelationRelationId &&
|
||||
deprec->objsubid == 0 &&
|
||||
deprec->refobjsubid != 0 &&
|
||||
deprec->deptype == DEPENDENCY_AUTO &&
|
||||
(deprec->deptype == DEPENDENCY_AUTO || deprec->deptype == DEPENDENCY_INTERNAL) &&
|
||||
get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
|
||||
{
|
||||
result = lappend_oid(result, deprec->objid);
|
||||
@@ -605,6 +598,21 @@ getOwnedSequences(Oid relid)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get owned sequence, error if not exactly one.
|
||||
*/
|
||||
Oid
|
||||
getOwnedSequence(Oid relid, AttrNumber attnum)
|
||||
{
|
||||
List *seqlist = getOwnedSequences(relid, attnum);
|
||||
|
||||
if (list_length(seqlist) > 1)
|
||||
elog(ERROR, "more than one owned sequence found");
|
||||
else if (list_length(seqlist) < 1)
|
||||
elog(ERROR, "no owned sequence found");
|
||||
else
|
||||
return linitial_oid(seqlist);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_constraint_index
|
||||
|
||||
Reference in New Issue
Block a user