mirror of
https://github.com/postgres/postgres.git
synced 2025-06-16 06:01:02 +03:00
Add temporal PRIMARY KEY and UNIQUE constraints
Add WITHOUT OVERLAPS clause to PRIMARY KEY and UNIQUE constraints. These are backed by GiST indexes instead of B-tree indexes, since they are essentially exclusion constraints with = for the scalar parts of the key and && for the temporal part. Author: Paul A. Jungwirth <pj@illuminatedcomputing.com> Reviewed-by: Peter Eisentraut <peter@eisentraut.org> Reviewed-by: jian he <jian.universality@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/CA+renyUApHgSZF9-nd-a0+OPGharLQLO=mDHcY4_qQ0+noCUVg@mail.gmail.com
This commit is contained in:
@ -1716,6 +1716,7 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx,
|
||||
index->unique = idxrec->indisunique;
|
||||
index->nulls_not_distinct = idxrec->indnullsnotdistinct;
|
||||
index->primary = idxrec->indisprimary;
|
||||
index->iswithoutoverlaps = (idxrec->indisprimary || idxrec->indisunique) && idxrec->indisexclusion;
|
||||
index->transformed = true; /* don't need transformIndexStmt */
|
||||
index->concurrent = false;
|
||||
index->if_not_exists = false;
|
||||
@ -1765,7 +1766,9 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx,
|
||||
int nElems;
|
||||
int i;
|
||||
|
||||
Assert(conrec->contype == CONSTRAINT_EXCLUSION);
|
||||
Assert(conrec->contype == CONSTRAINT_EXCLUSION ||
|
||||
(index->iswithoutoverlaps &&
|
||||
(conrec->contype == CONSTRAINT_PRIMARY || conrec->contype == CONSTRAINT_UNIQUE)));
|
||||
/* Extract operator OIDs from the pg_constraint tuple */
|
||||
datum = SysCacheGetAttrNotNull(CONSTROID, ht_constr,
|
||||
Anum_pg_constraint_conexclop);
|
||||
@ -2305,6 +2308,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
|
||||
}
|
||||
index->nulls_not_distinct = constraint->nulls_not_distinct;
|
||||
index->isconstraint = true;
|
||||
index->iswithoutoverlaps = constraint->without_overlaps;
|
||||
index->deferrable = constraint->deferrable;
|
||||
index->initdeferred = constraint->initdeferred;
|
||||
|
||||
@ -2397,6 +2401,11 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
|
||||
errmsg("index \"%s\" is not valid", index_name),
|
||||
parser_errposition(cxt->pstate, constraint->location)));
|
||||
|
||||
/*
|
||||
* Today we forbid non-unique indexes, but we could permit GiST
|
||||
* indexes whose last entry is a range type and use that to create a
|
||||
* WITHOUT OVERLAPS constraint (i.e. a temporal constraint).
|
||||
*/
|
||||
if (!index_form->indisunique)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
@ -2673,6 +2682,23 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
|
||||
notnullcmds = lappend(notnullcmds, notnullcmd);
|
||||
}
|
||||
}
|
||||
|
||||
if (constraint->without_overlaps)
|
||||
{
|
||||
/*
|
||||
* This enforces that there is at least one equality column
|
||||
* besides the WITHOUT OVERLAPS columns. This is per SQL
|
||||
* standard. XXX Do we need this?
|
||||
*/
|
||||
if (list_length(constraint->keys) < 2)
|
||||
ereport(ERROR,
|
||||
errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("constraint using WITHOUT OVERLAPS needs at least two columns"));
|
||||
|
||||
/* WITHOUT OVERLAPS requires a GiST index */
|
||||
index->accessMethod = "gist";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user