0001-fixup-Add-temporal-PRIMARY-KEY-and-UNIQUE-constraint.patch.nocfbot
text/plain
Filename: 0001-fixup-Add-temporal-PRIMARY-KEY-and-UNIQUE-constraint.patch.nocfbot
Type: text/plain
Part: 0
Message:
Re: SQL:2011 application time
From 6d7af1f78505c08fb205a56bd1ba3cb951f04002 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 9 Nov 2023 14:11:34 +0100
Subject: [PATCH] fixup! Add temporal PRIMARY KEY and UNIQUE constraints
---
doc/src/sgml/catalogs.sgml | 8 +--
doc/src/sgml/ref/create_table.sgml | 68 ++++++++-----------
src/backend/catalog/heap.c | 4 +-
src/backend/catalog/index.c | 14 ++--
src/backend/catalog/pg_constraint.c | 4 +-
src/backend/commands/indexcmds.c | 30 ++++----
src/backend/commands/tablecmds.c | 16 ++---
src/backend/commands/trigger.c | 2 +-
src/backend/commands/typecmds.c | 2 +-
src/backend/parser/gram.y | 19 +++---
src/backend/parser/parse_utilcmd.c | 28 ++++++--
src/backend/utils/adt/ruleutils.c | 27 +++-----
src/backend/utils/cache/relcache.c | 16 +++--
src/bin/pg_dump/pg_dump.c | 33 +++------
src/bin/pg_dump/pg_dump.h | 2 +-
src/bin/pg_dump/t/002_pg_dump.pl | 14 ++--
src/bin/psql/describe.c | 10 +--
src/include/catalog/index.h | 2 +-
src/include/catalog/pg_constraint.h | 11 +--
src/include/commands/defrem.h | 2 +-
src/include/nodes/parsenodes.h | 6 +-
.../regress/expected/without_overlaps.out | 8 +--
src/test/regress/parallel_schedule | 4 +-
23 files changed, 148 insertions(+), 182 deletions(-)
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 5412f2daa0..618a05ac89 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -2711,13 +2711,11 @@ <title><structname>pg_constraint</structname> Columns</title>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
- <structfield>contemporal</structfield> <type>bool</type>
+ <structfield>conwithoutoverlaps</structfield> <type>bool</type>
</para>
<para>
- This constraint is a application-time temporal constraint,
- defined with <literal>WITHOUT OVERLAPS</literal> (for primary
- key and unique constraints) or <literal>PERIOD</literal> (for
- foreign keys).
+ This constraint is defined with <literal>WITHOUT OVERLAPS</literal>
+ (for primary keys and unique constraints).
</para></entry>
</row>
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index ad5bf21453..a0bd2b8adc 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -78,8 +78,8 @@
[ CONSTRAINT <replaceable class="parameter">constraint_name</replaceable> ]
{ CHECK ( <replaceable class="parameter">expression</replaceable> ) [ NO INHERIT ] |
NOT NULL <replaceable class="parameter">column_name</replaceable> [ NO INHERIT ] |
- UNIQUE [ NULLS [ NOT ] DISTINCT ] ( <replaceable class="parameter">column_name</replaceable> [, ... ] [, <replaceable class="parameter">temporal_interval</replaceable> WITHOUT OVERLAPS ] ) <replaceable class="parameter">index_parameters</replaceable> |
- PRIMARY KEY ( <replaceable class="parameter">column_name</replaceable> [, ... ] [, <replaceable class="parameter">temporal_interval</replaceable> WITHOUT OVERLAPS ] ) <replaceable class="parameter">index_parameters</replaceable> |
+ UNIQUE [ NULLS [ NOT ] DISTINCT ] ( <replaceable class="parameter">column_name</replaceable> [, ... ] [, <replaceable class="parameter">column_name</replaceable> WITHOUT OVERLAPS ] ) <replaceable class="parameter">index_parameters</replaceable> |
+ PRIMARY KEY ( <replaceable class="parameter">column_name</replaceable> [, ... ] [, <replaceable class="parameter">column_name</replaceable> WITHOUT OVERLAPS ] ) <replaceable class="parameter">index_parameters</replaceable> |
EXCLUDE [ USING <replaceable class="parameter">index_method</replaceable> ] ( <replaceable class="parameter">exclude_element</replaceable> WITH <replaceable class="parameter">operator</replaceable> [, ... ] ) <replaceable class="parameter">index_parameters</replaceable> [ WHERE ( <replaceable class="parameter">predicate</replaceable> ) ] |
FOREIGN KEY ( <replaceable class="parameter">column_name</replaceable> [, ... ] ) REFERENCES <replaceable class="parameter">reftable</replaceable> [ ( <replaceable class="parameter">refcolumn</replaceable> [, ... ] ) ]
[ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE <replaceable
@@ -107,10 +107,6 @@
{ <replaceable class="parameter">column_name</replaceable> | ( <replaceable class="parameter">expression</replaceable> ) } [ <replaceable class="parameter">opclass</replaceable> ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]
-<phrase><replaceable class="parameter">temporal_interval</replaceable> in a <literal>PRIMARY KEY</literal>, <literal>UNIQUE</literal>, or <literal>FOREIGN KEY</literal> constraint is:</phrase>
-
-<replaceable class="parameter">range_column_name</replaceable>
-
<phrase><replaceable class="parameter">referential_action</replaceable> in a <literal>FOREIGN KEY</literal>/<literal>REFERENCES</literal> constraint is:</phrase>
{ NO ACTION | RESTRICT | CASCADE | SET NULL [ ( <replaceable class="parameter">column_name</replaceable> [, ... ] ) ] | SET DEFAULT [ ( <replaceable class="parameter">column_name</replaceable> [, ... ] ) ] }
@@ -969,7 +965,7 @@ <title>Parameters</title>
<varlistentry id="sql-createtable-parms-unique">
<term><literal>UNIQUE [ NULLS [ NOT ] DISTINCT ]</literal> (column constraint)</term>
- <term><literal>UNIQUE [ NULLS [ NOT ] DISTINCT ] ( <replaceable class="parameter">column_name</replaceable> [, ... ] )</literal>
+ <term><literal>UNIQUE [ NULLS [ NOT ] DISTINCT ] ( <replaceable class="parameter">column_name</replaceable> [, ... ] [, <replaceable class="parameter">column_name</replaceable> WITHOUT OVERLAPS ] )</literal>
<optional> <literal>INCLUDE ( <replaceable class="parameter">column_name</replaceable> [, ...])</literal> </optional> (table constraint)</term>
<listitem>
@@ -983,6 +979,26 @@ <title>Parameters</title>
of these columns.
</para>
+ <para>
+ If the <literal>WITHOUT OVERLAPS</literal> option is specified for the
+ last column, then that column is checked for overlaps instead of
+ equality. In that case, the other columns of the constraint will allow
+ duplicates so long as the duplicates don't overlap in the
+ <literal>WITHOUT OVERLAPS</literal> column. (This is sometimes called a
+ temporal key, if the column is a range of dates or timestamps, but
+ PostgreSQL allows ranges over any base type.) In effect, such a
+ constraint is enforced with an <literal>EXCLUDE</literal> constraint
+ rather than a <literal>UNIQUE</literal> constraint. So for example
+ <literal>UNIQUE (id, valid_at WITHOUT OVERLAPS)</literal> behaves like
+ <literal>EXCLUDE USING GIST (id WITH =, valid_at WITH
+ &&)</literal>. The <literal>WITHOUT OVERLAPS</literal> column
+ must have a range type. The non-<literal>WITHOUT OVERLAPS</literal>
+ columns of the constraint can be any type that can be compared for
+ equality in a GiST index. By default only range types are supported, but
+ you can use other types by adding the <xref linkend="btree-gist"/>
+ extension (which is the expected way to use this feature).
+ </para>
+
<para>
For the purpose of a unique constraint, null values are not
considered equal, unless <literal>NULLS NOT DISTINCT</literal> is
@@ -1007,8 +1023,7 @@ <title>Parameters</title>
Adding a unique constraint will automatically create a unique btree
index on the column or group of columns used in the constraint. But if
the constraint includes a <literal>WITHOUT OVERLAPS</literal> clause,
- it will use a GiST index and behave like a temporal <literal>PRIMARY
- KEY</literal>: preventing duplicates only in overlapping time periods.
+ it will use a GiST index.
</para>
<para>
@@ -1026,8 +1041,7 @@ <title>Parameters</title>
<varlistentry id="sql-createtable-parms-primary-key">
<term><literal>PRIMARY KEY</literal> (column constraint)</term>
- <term><literal>PRIMARY KEY ( <replaceable class="parameter">column_name</replaceable> [, ... ]
- [, <replaceable class="parameter">temporal_interval</replaceable> WITHOUT OVERLAPS ] )</literal>
+ <term><literal>PRIMARY KEY ( <replaceable class="parameter">column_name</replaceable> [, ... ] [, <replaceable class="parameter">column_name</replaceable> WITHOUT OVERLAPS ] )</literal>
<optional> <literal>INCLUDE ( <replaceable class="parameter">column_name</replaceable> [, ...])</literal> </optional> (table constraint)</term>
<listitem>
<para>
@@ -1060,9 +1074,10 @@ <title>Parameters</title>
</para>
<para>
- Adding a <literal>PRIMARY KEY</literal> constraint will automatically
- create a unique btree index (or GiST if temporal) on the column or group of
- columns used in the constraint.
+ As with a <literal>UNIQUE</literal> constraint, adding a
+ <literal>PRIMARY KEY</literal> constraint will automatically create a
+ unique btree index, or GiST if <literal>WITHOUT OVERLAPS</literal> was
+ specified, on the column or group of columns used in the constraint.
</para>
<para>
@@ -1075,31 +1090,6 @@ <title>Parameters</title>
(e.g., <literal>DROP COLUMN</literal>) can cause cascaded constraint and
index deletion.
</para>
-
- <para>
- A <literal>PRIMARY KEY</literal> with a <literal>WITHOUT OVERLAPS</literal> option
- is a <emphasis>temporal</emphasis> primary key.
- The <literal>WITHOUT OVERLAPS</literal> column
- must be a range type or a <literal>PERIOD</literal>
- and is used to constrain the record's applicability
- to just that range/period (usually a range of dates or timestamps,
- although Postgres allows a range/period over any base type).
- </para>
-
- <para>
- The non-<literal>WITHOUT OVERLAPS</literal> part(s) of the key can be any
- type that can be compared for equality in a GiST index. By default
- only range types are supported, but you can use other types by
- adding the <xref linkend="btree-gist"/> extension
- (which is the expected way to use this feature).
- These ordinary parts of the primary key do allow duplicates,
- so long as the duplicates don't overlap in the
- <literal>WITHOUT OVERLAPS</literal> column.
- In effect a temporal <literal>PRIMARY KEY</literal> is enforced with an
- <literal>EXCLUDE</literal> constraint rather than a <literal>UNIQUE</literal>
- constraint. So for example <literal>PRIMARY KEY (id, valid_at WITHOUT OVERLAPS)</literal>
- behaves like <literal>EXCLUDE USING GIST (id WITH =, valid_at WITH &&)</literal>.
- </para>
</listitem>
</varlistentry>
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 3e9cc4bb10..f126d8e676 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -2140,7 +2140,7 @@ StoreRelCheck(Relation rel, const char *ccname, Node *expr,
is_local, /* conislocal */
inhcount, /* coninhcount */
is_no_inherit, /* connoinherit */
- false, /* contemporal */
+ false, /* conwithoutoverlaps */
is_internal); /* internally constructed? */
pfree(ccbin);
@@ -2191,7 +2191,7 @@ StoreRelNotNull(Relation rel, const char *nnname, AttrNumber attnum,
is_local,
inhcount,
is_no_inherit,
- false, /* contemporal */
+ false, /* conwithoutoverlaps */
false);
return constrOid;
}
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 2f1ec3b0ac..8444d768e5 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -254,8 +254,8 @@ index_check_primary_key(Relation heapRel,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("primary keys cannot be expressions")));
- /* System attributes are never null, so no need to check. */
- if (attnum <= 0)
+ /* System attributes are never null, so no need to check */
+ if (attnum < 0)
continue;
atttuple = SearchSysCache2(ATTNUM,
@@ -1326,7 +1326,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
Anum_pg_index_indoption);
indcoloptions = (int2vector *) DatumGetPointer(colOptionDatum);
- /* Fetch options of index if any */
+ /* Fetch reloptions of index if any */
classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(oldIndexId));
if (!HeapTupleIsValid(classTuple))
elog(ERROR, "cache lookup failed for relation %u", oldIndexId);
@@ -1895,7 +1895,7 @@ index_concurrently_set_dead(Oid heapId, Oid indexId)
* INDEX_CONSTR_CREATE_UPDATE_INDEX: update the pg_index row
* INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS: remove existing dependencies
* of index on table's columns
- * INDEX_CONSTR_CREATE_TEMPORAL: constraint is for a temporal primary key
+ * INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS: constraint uses WITHOUT OVERLAPS
* allow_system_table_mods: allow table to be a system catalog
* is_internal: index is constructed due to internal process
*/
@@ -1919,13 +1919,13 @@ index_constraint_create(Relation heapRelation,
bool mark_as_primary;
bool islocal;
bool noinherit;
- bool is_temporal;
+ bool is_without_overlaps;
int inhcount;
deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0;
initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0;
mark_as_primary = (constr_flags & INDEX_CONSTR_CREATE_MARK_AS_PRIMARY) != 0;
- is_temporal = (constr_flags & INDEX_CONSTR_CREATE_TEMPORAL) != 0;
+ is_without_overlaps = (constr_flags & INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS) != 0;
/* constraint creation support doesn't work while bootstrapping */
Assert(!IsBootstrapProcessingMode());
@@ -2002,7 +2002,7 @@ index_constraint_create(Relation heapRelation,
islocal,
inhcount,
noinherit,
- is_temporal, /* contemporal */
+ is_without_overlaps,
is_internal);
/*
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index d5329ca8c9..ffd340a2e4 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -78,7 +78,7 @@ CreateConstraintEntry(const char *constraintName,
bool conIsLocal,
int conInhCount,
bool conNoInherit,
- bool conTemporal,
+ bool conWithoutOverlaps,
bool is_internal)
{
Relation conDesc;
@@ -194,7 +194,7 @@ CreateConstraintEntry(const char *constraintName,
values[Anum_pg_constraint_conislocal - 1] = BoolGetDatum(conIsLocal);
values[Anum_pg_constraint_coninhcount - 1] = Int16GetDatum(conInhCount);
values[Anum_pg_constraint_connoinherit - 1] = BoolGetDatum(conNoInherit);
- values[Anum_pg_constraint_contemporal - 1] = BoolGetDatum(conTemporal);
+ values[Anum_pg_constraint_conwithoutoverlaps - 1] = BoolGetDatum(conWithoutOverlaps);
if (conkeyArray)
values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray);
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index e9d1b17935..d56db81fa1 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -91,7 +91,7 @@ static void ComputeIndexAttrs(IndexInfo *indexInfo,
Oid accessMethodId,
bool amcanorder,
bool isconstraint,
- bool istemporal,
+ bool iswithoutoverlaps,
Oid ddl_userid,
int ddl_sec_context,
int *ddl_save_nestlevel);
@@ -149,7 +149,7 @@ typedef struct ReindexErrorInfo
* to index on.
* 'exclusionOpNames': list of names of exclusion-constraint operators,
* or NIL if not an exclusion constraint.
- * 'istemporal': true iff this index has a WITHOUT OVERLAPS clause.
+ * 'isWithoutOverlaps': true iff this index has a WITHOUT OVERLAPS clause.
*
* This is tailored to the needs of ALTER TABLE ALTER TYPE, which recreates
* any indexes that depended on a changing column from their pg_get_indexdef
@@ -180,7 +180,7 @@ CheckIndexCompatible(Oid oldId,
const char *accessMethodName,
const List *attributeList,
const List *exclusionOpNames,
- bool istemporal)
+ bool isWithoutOverlaps)
{
bool isconstraint;
Oid *typeIds;
@@ -255,7 +255,7 @@ CheckIndexCompatible(Oid oldId,
coloptions, attributeList,
exclusionOpNames, relationId,
accessMethodName, accessMethodId,
- amcanorder, isconstraint, istemporal, InvalidOid,
+ amcanorder, isconstraint, isWithoutOverlaps, InvalidOid,
0, NULL);
/* Get the soon-obsolete pg_index tuple. */
@@ -689,7 +689,7 @@ DefineIndex(Oid tableId,
* It has exclusion constraint behavior if it's an EXCLUDE constraint
* or a temporal PRIMARY KEY/UNIQUE constraint
*/
- exclusion = stmt->excludeOpNames || stmt->istemporal;
+ exclusion = stmt->excludeOpNames || stmt->iswithoutoverlaps;
/* Ensure that it makes sense to index this kind of relation */
switch (rel->rd_rel->relkind)
@@ -859,7 +859,7 @@ DefineIndex(Oid tableId,
pgstat_progress_update_param(PROGRESS_CREATEIDX_ACCESS_METHOD_OID,
accessMethodId);
- if (stmt->unique && !stmt->istemporal && !amRoutine->amcanunique)
+ if (stmt->unique && !stmt->iswithoutoverlaps && !amRoutine->amcanunique)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("access method \"%s\" does not support unique indexes",
@@ -927,7 +927,7 @@ DefineIndex(Oid tableId,
coloptions, allIndexParams,
stmt->excludeOpNames, tableId,
accessMethodName, accessMethodId,
- amcanorder, stmt->isconstraint, stmt->istemporal,
+ amcanorder, stmt->isconstraint, stmt->iswithoutoverlaps,
root_save_userid, root_save_sec_context,
&root_save_nestlevel);
@@ -955,8 +955,6 @@ DefineIndex(Oid tableId,
if (stmt->primary)
constraint_type = "PRIMARY KEY";
- else if (stmt->unique && stmt->istemporal)
- constraint_type = "temporal UNIQUE";
else if (stmt->unique)
constraint_type = "UNIQUE";
else if (stmt->excludeOpNames)
@@ -1006,7 +1004,7 @@ DefineIndex(Oid tableId,
* we have an exclusion constraint (or a temporal PK), it already
* knows the operators, so we don't have to infer them.
*/
- if (stmt->unique && !stmt->istemporal && accessMethodId != BTREE_AM_OID)
+ if (stmt->unique && !stmt->iswithoutoverlaps && accessMethodId != BTREE_AM_OID)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot match partition key to an index using access method \"%s\"",
@@ -1039,7 +1037,7 @@ DefineIndex(Oid tableId,
{
Oid idx_eqop = InvalidOid;
- if (stmt->unique && !stmt->istemporal)
+ if (stmt->unique && !stmt->iswithoutoverlaps)
idx_eqop = get_opfamily_member(idx_opfamily,
idx_opcintype,
idx_opcintype,
@@ -1197,8 +1195,8 @@ DefineIndex(Oid tableId,
constr_flags |= INDEX_CONSTR_CREATE_DEFERRABLE;
if (stmt->initdeferred)
constr_flags |= INDEX_CONSTR_CREATE_INIT_DEFERRED;
- if (stmt->istemporal)
- constr_flags |= INDEX_CONSTR_CREATE_TEMPORAL;
+ if (stmt->iswithoutoverlaps)
+ constr_flags |= INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS;
indexRelationId =
index_create(rel, indexRelationName, indexRelationId, parentIndexId,
@@ -1975,7 +1973,7 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
Oid accessMethodId,
bool amcanorder,
bool isconstraint,
- bool istemporal,
+ bool iswithoutoverlaps,
Oid ddl_userid,
int ddl_sec_context,
int *ddl_save_nestlevel)
@@ -2000,7 +1998,7 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
nextExclOp = NULL;
/* exclusionOpNames can be non-NIL if we are creating a partition */
- if (istemporal && exclusionOpNames == NIL)
+ if (iswithoutoverlaps && exclusionOpNames == NIL)
{
indexInfo->ii_ExclusionOps = palloc_array(Oid, nkeycols);
indexInfo->ii_ExclusionProcs = palloc_array(Oid, nkeycols);
@@ -2283,7 +2281,7 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
indexInfo->ii_ExclusionStrats[attn] = strat;
nextExclOp = lnext(exclusionOpNames, nextExclOp);
}
- else if (istemporal)
+ else if (iswithoutoverlaps)
{
int strat;
Oid opid;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 4cc645282a..04527a3540 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -208,7 +208,6 @@ typedef struct NewConstraint
Oid refrelid; /* PK rel, if FOREIGN */
Oid refindid; /* OID of PK's index, if FOREIGN */
Oid conid; /* OID of pg_constraint entry, if FOREIGN */
- bool contemporal; /* Whether the new constraint is temporal */
Node *qual; /* Check expr or CONSTR_FOREIGN Constraint */
ExprState *qualstate; /* Execution state for CHECK expr */
} NewConstraint;
@@ -10094,7 +10093,7 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel,
conislocal, /* islocal */
coninhcount, /* inhcount */
connoinherit, /* conNoInherit */
- false, /* conTemporal */
+ false, /* conWithoutOverlaps */
false); /* is_internal */
ObjectAddressSet(address, ConstraintRelationId, constrOid);
@@ -10393,7 +10392,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
false,
1,
false,
- false, /* conTemporal */
+ false, /* conWithoutOverlaps */
false);
/*
@@ -10899,7 +10898,7 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
false, /* islocal */
1, /* inhcount */
false, /* conNoInherit */
- false, /* conTemporal */
+ false, /* conWithoutOverlaps */
true);
/* Set up partition dependencies for the new constraint */
@@ -11574,7 +11573,6 @@ ATExecValidateConstraint(List **wqueue, Relation rel, char *constrName,
newcon->refrelid = con->confrelid;
newcon->refindid = con->conindid;
newcon->conid = con->oid;
- newcon->contemporal = con->contemporal;
newcon->qual = (Node *) fkconstraint;
/* Find or create work queue entry for this table */
@@ -11741,12 +11739,10 @@ transformColumnNameList(Oid relId, List *colList,
*
* Look up the names, attnums, and types of the primary key attributes
* for the pkrel. Also return the index OID and index opclasses of the
- * index supporting the primary key. If this is a temporal primary key,
- * also set the WITHOUT OVERLAPS attribute name, attnum, and atttypid.
+ * index supporting the primary key.
*
* All parameters except pkrel are output parameters. Also, the function
- * return value is the number of attributes in the primary key,
- * not including the WITHOUT OVERLAPS if any.
+ * return value is the number of attributes in the primary key.
*
* Used when the column list in the REFERENCES specification is omitted.
*/
@@ -14292,7 +14288,7 @@ TryReuseIndex(Oid oldId, IndexStmt *stmt)
stmt->accessMethod,
stmt->indexParams,
stmt->excludeOpNames,
- stmt->istemporal))
+ stmt->iswithoutoverlaps))
{
Relation irel = index_open(oldId, NoLock);
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 0577b60415..a10a42b97f 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -841,7 +841,7 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString,
true, /* islocal */
0, /* inhcount */
true, /* noinherit */
- false, /* contemporal */
+ false, /* conwithoutoverlaps */
isInternal); /* is_internal */
}
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 1773556053..2470019818 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -3544,7 +3544,7 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
true, /* is local */
0, /* inhcount */
false, /* connoinherit */
- false, /* contemporal */
+ false, /* conwithoutoverlaps */
false); /* is_internal */
if (constrAddr)
ObjectAddressSet(*constrAddr, ConstraintRelationId, ccoid);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 14d4e24fcc..ff4add6225 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -523,13 +523,12 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <node> TableElement TypedTableElement ConstraintElem TableFuncElement
%type <node> columnDef columnOptions
%type <defelt> def_elem reloption_elem old_aggr_elem operator_def_elem
-%type <node> def_arg columnElem without_overlaps_clause
- where_clause where_or_current_clause
+%type <node> def_arg columnElem where_clause where_or_current_clause
a_expr b_expr c_expr AexprConst indirection_el opt_slice_bound
columnref in_expr having_clause func_table xmltable array_expr
OptWhereClause operator_def_arg
%type <list> rowsfrom_item rowsfrom_list opt_col_def_list
-%type <boolean> opt_ordinality
+%type <boolean> opt_ordinality opt_without_overlaps
%type <list> ExclusionConstraintList ExclusionConstraintElem
%type <list> func_arg_list func_arg_list_opt
%type <node> func_arg_expr
@@ -4105,7 +4104,7 @@ ConstraintElem:
n->initially_valid = true;
$$ = (Node *) n;
}
- | UNIQUE opt_unique_null_treatment '(' columnList without_overlaps_clause ')' opt_c_include opt_definition OptConsTableSpace
+ | UNIQUE opt_unique_null_treatment '(' columnList opt_without_overlaps ')' opt_c_include opt_definition OptConsTableSpace
ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
@@ -4140,7 +4139,7 @@ ConstraintElem:
NULL, yyscanner);
$$ = (Node *) n;
}
- | PRIMARY KEY '(' columnList without_overlaps_clause ')' opt_c_include opt_definition OptConsTableSpace
+ | PRIMARY KEY '(' columnList opt_without_overlaps ')' opt_c_include opt_definition OptConsTableSpace
ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
@@ -4221,6 +4220,11 @@ opt_no_inherit: NO INHERIT { $$ = true; }
| /* EMPTY */ { $$ = false; }
;
+opt_without_overlaps:
+ WITHOUT OVERLAPS { $$ = true; }
+ | /*EMPTY*/ { $$ = false; }
+ ;
+
opt_column_list:
'(' columnList ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
@@ -4231,11 +4235,6 @@ columnList:
| columnList ',' columnElem { $$ = lappend($1, $3); }
;
-without_overlaps_clause:
- ',' columnElem WITHOUT OVERLAPS { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
-
columnElem: ColId
{
$$ = (Node *) makeString($1);
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index f4705ecc2b..547e3058b9 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -124,7 +124,7 @@ static List *get_opclass(Oid opclass, Oid actual_datatype);
static void transformIndexConstraints(CreateStmtContext *cxt);
static IndexStmt *transformIndexConstraint(Constraint *constraint,
CreateStmtContext *cxt);
-static void validateWithoutOverlaps(CreateStmtContext *cxt, char *colname, int location);
+static void validateWithoutOverlaps(CreateStmtContext *cxt, const char *colname, int location);
static void transformExtendedStatistics(CreateStmtContext *cxt);
static void transformFKConstraints(CreateStmtContext *cxt,
bool skipValidation,
@@ -1717,7 +1717,7 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx,
index->unique = idxrec->indisunique;
index->nulls_not_distinct = idxrec->indnullsnotdistinct;
index->primary = idxrec->indisprimary;
- index->istemporal = (idxrec->indisprimary || idxrec->indisunique) && idxrec->indisexclusion;
+ index->iswithoutoverlaps = (idxrec->indisprimary || idxrec->indisunique) && idxrec->indisexclusion;
index->transformed = true; /* don't need transformIndexStmt */
index->concurrent = false;
index->if_not_exists = false;
@@ -1768,7 +1768,7 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx,
int i;
Assert(conrec->contype == CONSTRAINT_EXCLUSION ||
- (index->istemporal &&
+ (index->iswithoutoverlaps &&
(conrec->contype == CONSTRAINT_PRIMARY || conrec->contype == CONSTRAINT_UNIQUE)));
/* Extract operator OIDs from the pg_constraint tuple */
datum = SysCacheGetAttrNotNull(CONSTROID, ht_constr,
@@ -2309,7 +2309,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
}
index->nulls_not_distinct = constraint->nulls_not_distinct;
index->isconstraint = true;
- index->istemporal = constraint->without_overlaps != NULL;
+ index->iswithoutoverlaps = constraint->without_overlaps;
index->deferrable = constraint->deferrable;
index->initdeferred = constraint->initdeferred;
@@ -2555,6 +2555,10 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
ListCell *columns;
IndexElem *iparam;
+ /* handled below */
+ if (constraint->without_overlaps && lc == list_last_cell(constraint->keys))
+ break;
+
/* Make sure referenced column exists. */
foreach(columns, cxt->columns)
{
@@ -2688,11 +2692,21 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
* Anything in without_overlaps should be included,
* but with the overlaps operator (&&) instead of equality.
*/
- if (constraint->without_overlaps != NULL)
+ if (constraint->without_overlaps)
{
- char *without_overlaps_str = strVal(constraint->without_overlaps);
+ char *without_overlaps_str = strVal(llast(constraint->keys));
IndexElem *iparam = makeNode(IndexElem);
+ /*
+ * This enforces that there is at last 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"));
+
/*
* Iterate through the table's columns
* (like just a little bit above).
@@ -2855,7 +2869,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
* and the new ones. Raises an error if we can't find one or it's not a range type.
*/
static void
-validateWithoutOverlaps(CreateStmtContext *cxt, char *colname, int location)
+validateWithoutOverlaps(CreateStmtContext *cxt, const char *colname, int location)
{
/* Check the new columns first in case their type is changing. */
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index f2da27eb50..25ac0ad1bc 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -338,7 +338,7 @@ static char *deparse_expression_pretty(Node *expr, List *dpcontext,
static char *pg_get_viewdef_worker(Oid viewoid,
int prettyFlags, int wrapColumn);
static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
-static int decompile_column_index_array(Datum column_index_array, Oid relId, Oid indexId,
+static int decompile_column_index_array(Datum column_index_array, Oid relId,
bool withoutOverlaps, StringInfo buf);
static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
@@ -2247,7 +2247,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
val = SysCacheGetAttrNotNull(CONSTROID, tup,
Anum_pg_constraint_conkey);
- decompile_column_index_array(val, conForm->conrelid, conForm->conindid, false, &buf);
+ decompile_column_index_array(val, conForm->conrelid, false, &buf);
/* add foreign relation name */
appendStringInfo(&buf, ") REFERENCES %s(",
@@ -2258,7 +2258,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
val = SysCacheGetAttrNotNull(CONSTROID, tup,
Anum_pg_constraint_confkey);
- decompile_column_index_array(val, conForm->confrelid, conForm->conindid, false, &buf);
+ decompile_column_index_array(val, conForm->confrelid, false, &buf);
appendStringInfoChar(&buf, ')');
@@ -2344,7 +2344,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
if (!isnull)
{
appendStringInfoString(&buf, " (");
- decompile_column_index_array(val, conForm->conrelid, InvalidOid, false, &buf);
+ decompile_column_index_array(val, conForm->conrelid, false, &buf);
appendStringInfoChar(&buf, ')');
}
@@ -2357,7 +2357,6 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
Oid indexId;
int keyatts;
HeapTuple indtup;
- bool isnull;
/* Start off the constraint definition */
if (conForm->contype == CONSTRAINT_PRIMARY)
@@ -2380,14 +2379,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
val = SysCacheGetAttrNotNull(CONSTROID, tup,
Anum_pg_constraint_conkey);
- /*
- * If it has exclusion-style operator OIDs
- * then it uses WITHOUT OVERLAPS.
- */
- indexId = conForm->conindid;
- SysCacheGetAttr(CONSTROID, tup,
- Anum_pg_constraint_conexclop, &isnull);
- keyatts = decompile_column_index_array(val, conForm->conrelid, indexId, !isnull, &buf);
+ keyatts = decompile_column_index_array(val, conForm->conrelid, conForm->conwithoutoverlaps, &buf);
appendStringInfoChar(&buf, ')');
@@ -2582,7 +2574,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
* of keys.
*/
static int
-decompile_column_index_array(Datum column_index_array, Oid relId, Oid indexId,
+decompile_column_index_array(Datum column_index_array, Oid relId,
bool withoutOverlaps, StringInfo buf)
{
Datum *keys;
@@ -2596,17 +2588,16 @@ decompile_column_index_array(Datum column_index_array, Oid relId, Oid indexId,
for (j = 0; j < nKeys; j++)
{
char *colName;
- int colid = DatumGetInt16(keys[j]);
- colName = get_attname(relId, colid, false);
+ colName = get_attname(relId, DatumGetInt16(keys[j]), false);
if (j == 0)
appendStringInfoString(buf, quote_identifier(colName));
- else if (withoutOverlaps && j == nKeys - 1)
- appendStringInfo(buf, ", %s WITHOUT OVERLAPS", quote_identifier(colName));
else
appendStringInfo(buf, ", %s", quote_identifier(colName));
}
+ if (withoutOverlaps)
+ appendStringInfoString(buf, " WITHOUT OVERLAPS");
return nKeys;
}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 45810ac35f..f341c5c370 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -5568,12 +5568,14 @@ RelationGetIdentityKeyBitmap(Relation relation)
/*
* RelationGetExclusionInfo -- get info about index's exclusion constraint
*
- * This should be called only for an index that is known to have an
- * associated exclusion constraint or temporal primary key/unique
- * constraint. It returns arrays (palloc'd in caller's context)
- * of the exclusion operator OIDs, their underlying functions'
- * OIDs, and their strategy numbers in the index's opclasses. We cache
- * all this information since it requires a fair amount of work to get.
+ * This should be called only for an index that is known to have an associated
+ * exclusion constraint or primary key/unique constraint using WITHOUT
+ * OVERLAPS.
+
+ * It returns arrays (palloc'd in caller's context) of the exclusion operator
+ * OIDs, their underlying functions' OIDs, and their strategy numbers in the
+ * index's opclasses. We cache all this information since it requires a fair
+ * amount of work to get.
*/
void
RelationGetExclusionInfo(Relation indexRelation,
@@ -5638,7 +5640,7 @@ RelationGetExclusionInfo(Relation indexRelation,
/* We want the exclusion constraint owning the index */
if ((conform->contype != CONSTRAINT_EXCLUSION &&
- !(conform->contemporal && (
+ !(conform->conwithoutoverlaps && (
conform->contype == CONSTRAINT_PRIMARY
|| conform->contype == CONSTRAINT_UNIQUE))) ||
conform->conindid != RelationGetRelid(indexRelation))
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 54a15cf64a..c89b6da8b2 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -6983,14 +6983,14 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
i_conname,
i_condeferrable,
i_condeferred,
+ i_conwithoutoverlaps,
i_contableoid,
i_conoid,
i_condef,
i_tablespace,
i_indreloptions,
i_indstatcols,
- i_indstatvals,
- i_withoutoverlaps;
+ i_indstatvals;
/*
* We want to perform just one query against pg_index. However, we
@@ -7072,10 +7072,10 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
if (fout->remoteVersion >= 170000)
appendPQExpBufferStr(query,
- "c.conexclop IS NOT NULL AS withoutoverlaps ");
+ "c.conwithoutoverlaps ");
else
appendPQExpBufferStr(query,
- "null AS withoutoverlaps ");
+ "NULL AS conwithoutoverlaps ");
/*
* The point of the messy-looking outer join is to find a constraint that
@@ -7143,6 +7143,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
i_conname = PQfnumber(res, "conname");
i_condeferrable = PQfnumber(res, "condeferrable");
i_condeferred = PQfnumber(res, "condeferred");
+ i_conwithoutoverlaps = PQfnumber(res, "conwithoutoverlaps");
i_contableoid = PQfnumber(res, "contableoid");
i_conoid = PQfnumber(res, "conoid");
i_condef = PQfnumber(res, "condef");
@@ -7150,7 +7151,6 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
i_indreloptions = PQfnumber(res, "indreloptions");
i_indstatcols = PQfnumber(res, "indstatcols");
i_indstatvals = PQfnumber(res, "indstatvals");
- i_withoutoverlaps = PQfnumber(res, "withoutoverlaps");
indxinfo = (IndxInfo *) pg_malloc(ntups * sizeof(IndxInfo));
@@ -7251,9 +7251,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
constrinfo->conindex = indxinfo[j].dobj.dumpId;
constrinfo->condeferrable = *(PQgetvalue(res, j, i_condeferrable)) == 't';
constrinfo->condeferred = *(PQgetvalue(res, j, i_condeferred)) == 't';
+ constrinfo->conwithoutoverlaps = *(PQgetvalue(res, j, i_conwithoutoverlaps)) == 't';
constrinfo->conislocal = true;
constrinfo->separate = true;
- constrinfo->withoutoverlaps = *(PQgetvalue(res, j, i_withoutoverlaps)) == 't';
indxinfo[j].indexconstraint = constrinfo->dobj.dumpId;
}
@@ -16949,23 +16949,12 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo)
break;
attname = getAttrName(indkey, tbinfo);
- if (k == 0)
- {
- appendPQExpBuffer(q, "%s",
- fmtId(attname));
- }
- else if (k == indxinfo->indnkeyattrs - 1 &&
- coninfo->withoutoverlaps)
- {
- appendPQExpBuffer(q, ", %s WITHOUT OVERLAPS",
- fmtId(attname));
- }
- else
- {
- appendPQExpBuffer(q, ", %s",
- fmtId(attname));
- }
+ appendPQExpBuffer(q, "%s%s",
+ (k == 0) ? "" : ", ",
+ fmtId(attname));
}
+ if (coninfo->conwithoutoverlaps)
+ appendPQExpBufferStr(q, " WITHOUT OVERLAPS");
if (indxinfo->indnkeyattrs < indxinfo->indnattrs)
appendPQExpBufferStr(q, ") INCLUDE (");
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index ad7cc85b8c..cbf4b5e179 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -487,9 +487,9 @@ typedef struct _constraintInfo
DumpId conindex; /* identifies associated index if any */
bool condeferrable; /* true if constraint is DEFERRABLE */
bool condeferred; /* true if constraint is INITIALLY DEFERRED */
+ bool conwithoutoverlaps; /* true if the constraint is WITHOUT OVERLAPS */
bool conislocal; /* true if constraint has local definition */
bool separate; /* true if must dump as separate item */
- bool withoutoverlaps; /* true if the last elem is WITHOUT OVERLAPS */
} ConstraintInfo;
typedef struct _procLangInfo
diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl
index eb35d5ef60..8584a4b406 100644
--- a/src/bin/pg_dump/t/002_pg_dump.pl
+++ b/src/bin/pg_dump/t/002_pg_dump.pl
@@ -1015,12 +1015,11 @@
},
},
- 'ALTER TABLE ONLY test_table_tpk ADD CONSTRAINT ... PRIMARY KEY (..., ... WITHOUT OVERLAPS)' => {
+ 'CONSTRAINT PRIMARY KEY / WITHOUT OVERLAPS' => {
create_sql => 'CREATE TABLE dump_test.test_table_tpk (
col1 int4range,
col2 tstzrange,
- CONSTRAINT test_table_tpk_pkey PRIMARY KEY
- (col1, col2 WITHOUT OVERLAPS));',
+ CONSTRAINT test_table_tpk_pkey PRIMARY KEY (col1, col2 WITHOUT OVERLAPS));',
regexp => qr/^
\QALTER TABLE ONLY dump_test.test_table_tpk\E \n^\s+
\QADD CONSTRAINT test_table_tpk_pkey PRIMARY KEY (col1, col2 WITHOUT OVERLAPS);\E
@@ -1029,21 +1028,18 @@
%full_runs,
%dump_test_schema_runs,
section_post_data => 1,
- exclude_test_table => 1,
},
unlike => {
- only_dump_test_table => 1,
exclude_dump_test_schema => 1,
only_dump_measurement => 1,
},
},
- 'ALTER TABLE ONLY test_table_tuq ADD CONSTRAINT ... UNIQUE (..., ... WITHOUT OVERLAPS)' => {
+ 'CONSTRAINT UNIQUE / WITHOUT OVERLAPS' => {
create_sql => 'CREATE TABLE dump_test.test_table_tuq (
col1 int4range,
col2 tstzrange,
- CONSTRAINT test_table_tuq_uq UNIQUE
- (col1, col2 WITHOUT OVERLAPS));',
+ CONSTRAINT test_table_tuq_uq UNIQUE (col1, col2 WITHOUT OVERLAPS));',
regexp => qr/^
\QALTER TABLE ONLY dump_test.test_table_tuq\E \n^\s+
\QADD CONSTRAINT test_table_tuq_uq UNIQUE (col1, col2 WITHOUT OVERLAPS);\E
@@ -1052,10 +1048,8 @@
%full_runs,
%dump_test_schema_runs,
section_post_data => 1,
- exclude_test_table => 1,
},
unlike => {
- only_dump_test_table => 1,
exclude_dump_test_schema => 1,
only_dump_measurement => 1,
},
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 4fbfc07460..135585411a 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -2384,10 +2384,10 @@ describeOneTableDetails(const char *schemaname,
else
appendPQExpBufferStr(&buf, ", false AS indisreplident");
appendPQExpBufferStr(&buf, ", c2.reltablespace");
- if (pset.sversion >= 160000)
- appendPQExpBufferStr(&buf, ", con.contemporal");
+ if (pset.sversion >= 170000)
+ appendPQExpBufferStr(&buf, ", con.conwithoutoverlaps");
else
- appendPQExpBufferStr(&buf, ", false AS contemporal");
+ appendPQExpBufferStr(&buf, ", false AS conwithoutoverlaps");
appendPQExpBuffer(&buf,
"\nFROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i\n"
" LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x'))\n"
@@ -2410,8 +2410,8 @@ describeOneTableDetails(const char *schemaname,
PQgetvalue(result, i, 0));
/*
- * If exclusion constraint or temporal PK/UNIQUE constraint,
- * print the constraintdef
+ * If exclusion constraint or PK/UNIQUE constraint WITHOUT
+ * OVERLAPS, print the constraintdef
*/
if (strcmp(PQgetvalue(result, i, 7), "x") == 0 ||
strcmp(PQgetvalue(result, i, 12), "t") == 0)
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 1a858c3897..0fccff9c05 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -92,7 +92,7 @@ extern Oid index_create(Relation heapRelation,
#define INDEX_CONSTR_CREATE_INIT_DEFERRED (1 << 2)
#define INDEX_CONSTR_CREATE_UPDATE_INDEX (1 << 3)
#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS (1 << 4)
-#define INDEX_CONSTR_CREATE_TEMPORAL (1 << 5)
+#define INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS (1 << 5)
extern Oid index_concurrently_create_copy(Relation heapRelation,
Oid oldIndexId,
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index 98a560741d..c17b1e9d31 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -108,10 +108,10 @@ CATALOG(pg_constraint,2606,ConstraintRelationId)
bool connoinherit;
/*
- * For primary and foreign keys, signifies the last column is a range
- * and should use overlaps instead of equals.
+ * For primary keys and unique constraints, signifies the last column uses
+ * overlaps instead of equals.
*/
- bool contemporal;
+ bool conwithoutoverlaps;
#ifdef CATALOG_VARLEN /* variable-length fields start here */
@@ -152,7 +152,8 @@ CATALOG(pg_constraint,2606,ConstraintRelationId)
/*
* If an exclusion constraint, the OIDs of the exclusion operators for
- * each column of the constraint. Also set for temporal primary keys.
+ * each column of the constraint. Also set for unique constraints/primary
+ * keys using WITHOUT OVERLAPS.
*/
Oid conexclop[1] BKI_LOOKUP(pg_operator);
@@ -242,7 +243,7 @@ extern Oid CreateConstraintEntry(const char *constraintName,
bool conIsLocal,
int conInhCount,
bool conNoInherit,
- bool conTemporal,
+ bool conWithoutOverlaps,
bool is_internal);
extern bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId,
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index f10886f6ca..25f55c181b 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -45,7 +45,7 @@ extern bool CheckIndexCompatible(Oid oldId,
const char *accessMethodName,
const List *attributeList,
const List *exclusionOpNames,
- bool istemporal);
+ bool isWithoutOverlaps);
extern Oid GetDefaultOpClass(Oid type_id, Oid am_id);
extern Oid ResolveOpClass(const List *opclass, Oid attrType,
const char *accessMethodName, Oid accessMethodId);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ff65db2db1..098990dd16 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2589,6 +2589,7 @@ typedef struct Constraint
bool nulls_not_distinct; /* null treatment for UNIQUE constraints */
List *keys; /* String nodes naming referenced key
* column(s); also used for NOT NULL */
+ bool without_overlaps; /* WITHOUT OVERLAPS specified */
List *including; /* String nodes naming referenced nonkey
* column(s) */
@@ -2617,9 +2618,6 @@ typedef struct Constraint
Oid old_pktable_oid; /* pg_constraint.confrelid of my former
* self */
- /* Fields used for temporal PRIMARY KEY and FOREIGN KEY constraints: */
- Node *without_overlaps; /* String node naming range column */
-
/* Fields used for constraints that allow a NOT VALID specification */
bool skip_validation; /* skip validation of existing rows? */
bool initially_valid; /* mark the new constraint as valid? */
@@ -3221,7 +3219,7 @@ typedef struct IndexStmt
bool nulls_not_distinct; /* null treatment for UNIQUE constraints */
bool primary; /* is index a primary key? */
bool isconstraint; /* is it for a pkey/unique constraint? */
- bool istemporal; /* is it for a temporal pkey? */
+ bool iswithoutoverlaps; /* is the constraint WITHOUT OVERLAPS? */
bool deferrable; /* is the constraint DEFERRABLE? */
bool initdeferred; /* is the constraint INITIALLY DEFERRED? */
bool transformed; /* true when transformIndexStmt is finished */
diff --git a/src/test/regress/expected/without_overlaps.out b/src/test/regress/expected/without_overlaps.out
index 36aebc452f..e565490a38 100644
--- a/src/test/regress/expected/without_overlaps.out
+++ b/src/test/regress/expected/without_overlaps.out
@@ -11,9 +11,7 @@ CREATE TABLE temporal_rng (
valid_at tsrange,
CONSTRAINT temporal_rng_pk PRIMARY KEY (valid_at WITHOUT OVERLAPS)
);
-ERROR: syntax error at or near "WITHOUT"
-LINE 3: CONSTRAINT temporal_rng_pk PRIMARY KEY (valid_at WITHOUT OV...
- ^
+ERROR: constraint using WITHOUT OVERLAPS needs at least two columns
-- PK with a range column/PERIOD that isn't there:
CREATE TABLE temporal_rng (
id INTEGER,
@@ -106,9 +104,7 @@ CREATE TABLE temporal_rng3 (
valid_at tsrange,
CONSTRAINT temporal_rng3_uq UNIQUE (valid_at WITHOUT OVERLAPS)
);
-ERROR: syntax error at or near "WITHOUT"
-LINE 3: CONSTRAINT temporal_rng3_uq UNIQUE (valid_at WITHOUT OVERLA...
- ^
+ERROR: constraint using WITHOUT OVERLAPS needs at least two columns
-- UNIQUE with a range column/PERIOD that isn't there:
CREATE TABLE temporal_rng3 (
id INTEGER,
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 16683148d2..b08aaae44b 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -28,7 +28,7 @@ test: strings md5 numerology point lseg line box path polygon circle date time t
# geometry depends on point, lseg, line, box, path, polygon, circle
# horology depends on date, time, timetz, timestamp, timestamptz, interval
# ----------
-test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc without_overlaps
+test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc
# ----------
# Load huge amounts of data
@@ -78,7 +78,7 @@ test: brin_bloom brin_multi
# psql depends on create_am
# amutils depends on geometry, create_index_spgist, hash_index, brin
# ----------
-test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role
+test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role without_overlaps
# collate.*.utf8 tests cannot be run in parallel with each other
test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 collate.windows.win1252
--
2.42.0