Hi
Already mentioned this in
https://postgr.es/m/[email protected]
While trying to add support for foreign keys to partitioned tables, I
noticed that commit 8224de4f42cc ("Indexes with INCLUDE columns and
their support in B-tree") added a column to pg_constraint that appears
to be there only to enable ruleutils.c to print out the list of columns
in a PRIMARY KEY or UNIQUE constraint that uses included columns.
However, this is pretty easy to obtain from pg_index.conkey instead, so
I claim that that column is useless. In fact, here's a patch to remove
it.
This requires a catversion bump, for which it may seem a bit late;
however I think it's better to release pg11 without a useless catalog
column only to remove it in pg12 ...
Thoughts?
--
Álvaro Herrera
>From 5e9c74c4dc59afb348b8b3ea5233b7cbf43c0616 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <[email protected]>
Date: Sun, 2 Sep 2018 13:35:46 -0300
Subject: [PATCH] remove conincluding
---
doc/src/sgml/catalogs.sgml | 8 ----
src/backend/catalog/pg_constraint.c | 21 ----------
src/backend/utils/adt/ruleutils.c | 57 +++++++++++++++++++++------
src/include/catalog/pg_constraint.h | 6 ---
src/test/regress/expected/index_including.out | 40 +++++++++----------
src/test/regress/sql/index_including.sql | 10 ++---
6 files changed, 70 insertions(+), 72 deletions(-)
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 07e8b3325f..0179deea2e 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -2374,14 +2374,6 @@ SCRAM-SHA-256$<replaceable><iteration
count></replaceable>:<replaceable>&l
</row>
<row>
- <entry><structfield>conincluding</structfield></entry>
- <entry><type>int2[]</type></entry>
- <entry><literal><link
linkend="catalog-pg-attribute"><structname>pg_attribute</structname></link>.attnum</literal></entry>
- <entry>List of the non-constrained columns which are included into
- the same index as the constrained columns</entry>
- </row>
-
- <row>
<entry><structfield>confkey</structfield></entry>
<entry><type>int2[]</type></entry>
<entry><literal><link
linkend="catalog-pg-attribute"><structname>pg_attribute</structname></link>.attnum</literal></entry>
diff --git a/src/backend/catalog/pg_constraint.c
b/src/backend/catalog/pg_constraint.c
index 7a6d158f89..ea84441360 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -85,7 +85,6 @@ CreateConstraintEntry(const char *constraintName,
bool nulls[Natts_pg_constraint];
Datum values[Natts_pg_constraint];
ArrayType *conkeyArray;
- ArrayType *conincludingArray;
ArrayType *confkeyArray;
ArrayType *conpfeqopArray;
ArrayType *conppeqopArray;
@@ -116,21 +115,6 @@ CreateConstraintEntry(const char *constraintName,
else
conkeyArray = NULL;
- if (constraintNTotalKeys > constraintNKeys)
- {
- Datum *conincluding;
- int j = 0;
- int constraintNIncludedKeys =
constraintNTotalKeys - constraintNKeys;
-
- conincluding = (Datum *) palloc(constraintNIncludedKeys *
sizeof(Datum));
- for (i = constraintNKeys; i < constraintNTotalKeys; i++)
- conincluding[j++] = Int16GetDatum(constraintKey[i]);
- conincludingArray = construct_array(conincluding,
constraintNIncludedKeys,
-
INT2OID, 2, true, 's');
- }
- else
- conincludingArray = NULL;
-
if (foreignNKeys > 0)
{
Datum *fkdatums;
@@ -204,11 +188,6 @@ CreateConstraintEntry(const char *constraintName,
else
nulls[Anum_pg_constraint_conkey - 1] = true;
- if (conincludingArray)
- values[Anum_pg_constraint_conincluding - 1] =
PointerGetDatum(conincludingArray);
- else
- nulls[Anum_pg_constraint_conincluding - 1] = true;
-
if (confkeyArray)
values[Anum_pg_constraint_confkey - 1] =
PointerGetDatum(confkeyArray);
else
diff --git a/src/backend/utils/adt/ruleutils.c
b/src/backend/utils/adt/ruleutils.c
index 03e9a28a63..bd0792e13e 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -315,7 +315,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 void decompile_column_index_array(Datum column_index_array, Oid relId,
+static int decompile_column_index_array(Datum column_index_array, Oid
relId,
StringInfo buf);
static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
@@ -2055,6 +2055,8 @@ pg_get_constraintdef_worker(Oid constraintId, bool
fullCommand,
Datum val;
bool isnull;
Oid indexId;
+ int keyatts;
+ HeapTuple indtup;
/* Start off the constraint definition */
if (conForm->contype == CONSTRAINT_PRIMARY)
@@ -2069,24 +2071,52 @@ pg_get_constraintdef_worker(Oid constraintId, bool
fullCommand,
elog(ERROR, "null conkey for constraint
%u",
constraintId);
- decompile_column_index_array(val,
conForm->conrelid, &buf);
+ keyatts = decompile_column_index_array(val,
conForm->conrelid, &buf);
appendStringInfoChar(&buf, ')');
- /* Fetch and build including column list */
- isnull = true;
- val = SysCacheGetAttr(CONSTROID, tup,
-
Anum_pg_constraint_conincluding, &isnull);
- if (!isnull)
+ indexId = get_constraint_index(constraintId);
+
+ /* Build including column list (from
pg_index.indkeys) */
+ indtup = SearchSysCache1(INDEXRELID,
ObjectIdGetDatum(indexId));
+ if (!HeapTupleIsValid(indtup))
+ elog(ERROR, "cache lookup failed for
index %u", indexId);
+ val = SysCacheGetAttr(INDEXRELID, indtup,
+
Anum_pg_index_indnatts, &isnull);
+ if (isnull)
+ elog(ERROR, "null indnatts for index
%u", indexId);
+ if (DatumGetInt32(val) > keyatts)
{
+ Datum cols;
+ Datum *keys;
+ int nKeys;
+ int j;
+
appendStringInfoString(&buf, " INCLUDE
(");
- decompile_column_index_array(val,
conForm->conrelid, &buf);
+ cols = SysCacheGetAttr(INDEXRELID,
indtup,
+
Anum_pg_index_indkey, &isnull);
+ if (isnull)
+ elog(ERROR, "null indkey for
index %u", indexId);
+
+
deconstruct_array(DatumGetArrayTypeP(cols),
+
INT2OID, 2, true, 's',
+
&keys, NULL, &nKeys);
+
+ for (j = keyatts; j < nKeys; j++)
+ {
+ char *colName;
+
+ colName =
get_attname(conForm->conrelid, DatumGetInt16(keys[j]), false);
+ if (j == keyatts)
+
appendStringInfoString(&buf, quote_identifier(colName));
+ else
+ appendStringInfo(&buf,
", %s", quote_identifier(colName));
+ }
appendStringInfoChar(&buf, ')');
}
-
- indexId = get_constraint_index(constraintId);
+ ReleaseSysCache(indtup);
/* XXX why do we only print these bits if
fullCommand? */
if (fullCommand && OidIsValid(indexId))
@@ -2232,9 +2262,10 @@ pg_get_constraintdef_worker(Oid constraintId, bool
fullCommand,
/*
* Convert an int16[] Datum into a comma-separated list of column names
- * for the indicated relation; append the list to buf.
+ * for the indicated relation; append the list to buf. Returns the number
+ * of keys.
*/
-static void
+static int
decompile_column_index_array(Datum column_index_array, Oid relId,
StringInfo buf)
{
@@ -2258,6 +2289,8 @@ decompile_column_index_array(Datum column_index_array,
Oid relId,
else
appendStringInfo(buf, ", %s",
quote_identifier(colName));
}
+
+ return nKeys;
}
diff --git a/src/include/catalog/pg_constraint.h
b/src/include/catalog/pg_constraint.h
index 7c1c0e1db8..9d209c9d19 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -106,12 +106,6 @@ CATALOG(pg_constraint,2606,ConstraintRelationId)
int16 conkey[1];
/*
- * Columns of conrelid that the constraint does not apply to, but are
- * included into the same index as the key columns
- */
- int16 conincluding[1];
-
- /*
* If a foreign key, the referenced columns of confrelid
*/
int16 confkey[1];
diff --git a/src/test/regress/expected/index_including.out
b/src/test/regress/expected/index_including.out
index 45a1c8d017..16b4be34de 100644
--- a/src/test/regress/expected/index_including.out
+++ b/src/test/regress/expected/index_including.out
@@ -94,10 +94,10 @@ SELECT indexrelid::regclass, indnatts, indnkeyatts,
indisunique, indisprimary, i
covering | 4 | 2 | t | f | 1 2 3 4 |
1978 1978
(1 row)
-SELECT pg_get_constraintdef(oid), conname, conkey, conincluding FROM
pg_constraint WHERE conrelid = 'tbl'::regclass::oid;
- pg_get_constraintdef | conname | conkey | conincluding
-----------------------------------+----------+--------+--------------
- UNIQUE (c1, c2) INCLUDE (c3, c4) | covering | {1,2} | {3,4}
+SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE
conrelid = 'tbl'::regclass::oid;
+ pg_get_constraintdef | conname | conkey
+----------------------------------+----------+--------
+ UNIQUE (c1, c2) INCLUDE (c3, c4) | covering | {1,2}
(1 row)
-- ensure that constraint works
@@ -113,10 +113,10 @@ SELECT indexrelid::regclass, indnatts, indnkeyatts,
indisunique, indisprimary, i
covering | 4 | 2 | t | t | 1 2 3 4 |
1978 1978
(1 row)
-SELECT pg_get_constraintdef(oid), conname, conkey, conincluding FROM
pg_constraint WHERE conrelid = 'tbl'::regclass::oid;
- pg_get_constraintdef | conname | conkey | conincluding
----------------------------------------+----------+--------+--------------
- PRIMARY KEY (c1, c2) INCLUDE (c3, c4) | covering | {1,2} | {3,4}
+SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE
conrelid = 'tbl'::regclass::oid;
+ pg_get_constraintdef | conname | conkey
+---------------------------------------+----------+--------
+ PRIMARY KEY (c1, c2) INCLUDE (c3, c4) | covering | {1,2}
(1 row)
-- ensure that constraint works
@@ -136,10 +136,10 @@ SELECT indexrelid::regclass, indnatts, indnkeyatts,
indisunique, indisprimary, i
tbl_c1_c2_c3_c4_key | 4 | 2 | t | f | 1
2 3 4 | 1978 1978
(1 row)
-SELECT pg_get_constraintdef(oid), conname, conkey, conincluding FROM
pg_constraint WHERE conrelid = 'tbl'::regclass::oid;
- pg_get_constraintdef | conname | conkey |
conincluding
-----------------------------------+---------------------+--------+--------------
- UNIQUE (c1, c2) INCLUDE (c3, c4) | tbl_c1_c2_c3_c4_key | {1,2} | {3,4}
+SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE
conrelid = 'tbl'::regclass::oid;
+ pg_get_constraintdef | conname | conkey
+----------------------------------+---------------------+--------
+ UNIQUE (c1, c2) INCLUDE (c3, c4) | tbl_c1_c2_c3_c4_key | {1,2}
(1 row)
-- ensure that constraint works
@@ -155,10 +155,10 @@ SELECT indexrelid::regclass, indnatts, indnkeyatts,
indisunique, indisprimary, i
tbl_pkey | 4 | 2 | t | t | 1 2 3 4 |
1978 1978
(1 row)
-SELECT pg_get_constraintdef(oid), conname, conkey, conincluding FROM
pg_constraint WHERE conrelid = 'tbl'::regclass::oid;
- pg_get_constraintdef | conname | conkey | conincluding
----------------------------------------+----------+--------+--------------
- PRIMARY KEY (c1, c2) INCLUDE (c3, c4) | tbl_pkey | {1,2} | {3,4}
+SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE
conrelid = 'tbl'::regclass::oid;
+ pg_get_constraintdef | conname | conkey
+---------------------------------------+----------+--------
+ PRIMARY KEY (c1, c2) INCLUDE (c3, c4) | tbl_pkey | {1,2}
(1 row)
-- ensure that constraint works
@@ -178,10 +178,10 @@ SELECT indexrelid::regclass, indnatts, indnkeyatts,
indisunique, indisprimary, i
tbl_c1_c3_c4_excl | 3 | 1 | f | f | 1 3
4 | 1978
(1 row)
-SELECT pg_get_constraintdef(oid), conname, conkey, conincluding FROM
pg_constraint WHERE conrelid = 'tbl'::regclass::oid;
- pg_get_constraintdef | conname | conkey
| conincluding
---------------------------------------------------+-------------------+--------+--------------
- EXCLUDE USING btree (c1 WITH =) INCLUDE (c3, c4) | tbl_c1_c3_c4_excl | {1}
| {3,4}
+SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE
conrelid = 'tbl'::regclass::oid;
+ pg_get_constraintdef | conname | conkey
+--------------------------------------------------+-------------------+--------
+ EXCLUDE USING btree (c1 WITH =) INCLUDE (c3, c4) | tbl_c1_c3_c4_excl | {1}
(1 row)
-- ensure that constraint works
diff --git a/src/test/regress/sql/index_including.sql
b/src/test/regress/sql/index_including.sql
index ee9d9f6bae..ef5fd882f5 100644
--- a/src/test/regress/sql/index_including.sql
+++ b/src/test/regress/sql/index_including.sql
@@ -60,7 +60,7 @@ ALTER TABLE tbl_include_box_pk add PRIMARY KEY (c1, c2)
INCLUDE (c3, c4);
CREATE TABLE tbl (c1 int,c2 int, c3 int, c4 box,
CONSTRAINT covering UNIQUE(c1,c2)
INCLUDE(c3,c4));
SELECT indexrelid::regclass, indnatts, indnkeyatts, indisunique, indisprimary,
indkey, indclass FROM pg_index WHERE indrelid = 'tbl'::regclass::oid;
-SELECT pg_get_constraintdef(oid), conname, conkey, conincluding FROM
pg_constraint WHERE conrelid = 'tbl'::regclass::oid;
+SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE
conrelid = 'tbl'::regclass::oid;
-- ensure that constraint works
INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS
x;
DROP TABLE tbl;
@@ -68,7 +68,7 @@ DROP TABLE tbl;
CREATE TABLE tbl (c1 int,c2 int, c3 int, c4 box,
CONSTRAINT covering PRIMARY KEY(c1,c2)
INCLUDE(c3,c4));
SELECT indexrelid::regclass, indnatts, indnkeyatts, indisunique, indisprimary,
indkey, indclass FROM pg_index WHERE indrelid = 'tbl'::regclass::oid;
-SELECT pg_get_constraintdef(oid), conname, conkey, conincluding FROM
pg_constraint WHERE conrelid = 'tbl'::regclass::oid;
+SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE
conrelid = 'tbl'::regclass::oid;
-- ensure that constraint works
INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS
x;
INSERT INTO tbl SELECT 1, NULL, 3*x, box('4,4,4,4') FROM generate_series(1,10)
AS x;
@@ -78,7 +78,7 @@ DROP TABLE tbl;
CREATE TABLE tbl (c1 int,c2 int, c3 int, c4 box,
UNIQUE(c1,c2) INCLUDE(c3,c4));
SELECT indexrelid::regclass, indnatts, indnkeyatts, indisunique, indisprimary,
indkey, indclass FROM pg_index WHERE indrelid = 'tbl'::regclass::oid;
-SELECT pg_get_constraintdef(oid), conname, conkey, conincluding FROM
pg_constraint WHERE conrelid = 'tbl'::regclass::oid;
+SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE
conrelid = 'tbl'::regclass::oid;
-- ensure that constraint works
INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS
x;
DROP TABLE tbl;
@@ -86,7 +86,7 @@ DROP TABLE tbl;
CREATE TABLE tbl (c1 int,c2 int, c3 int, c4 box,
PRIMARY KEY(c1,c2) INCLUDE(c3,c4));
SELECT indexrelid::regclass, indnatts, indnkeyatts, indisunique, indisprimary,
indkey, indclass FROM pg_index WHERE indrelid = 'tbl'::regclass::oid;
-SELECT pg_get_constraintdef(oid), conname, conkey, conincluding FROM
pg_constraint WHERE conrelid = 'tbl'::regclass::oid;
+SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE
conrelid = 'tbl'::regclass::oid;
-- ensure that constraint works
INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS
x;
INSERT INTO tbl SELECT 1, NULL, 3*x, box('4,4,4,4') FROM generate_series(1,10)
AS x;
@@ -96,7 +96,7 @@ DROP TABLE tbl;
CREATE TABLE tbl (c1 int,c2 int, c3 int, c4 box,
EXCLUDE USING btree (c1 WITH =) INCLUDE(c3,c4));
SELECT indexrelid::regclass, indnatts, indnkeyatts, indisunique, indisprimary,
indkey, indclass FROM pg_index WHERE indrelid = 'tbl'::regclass::oid;
-SELECT pg_get_constraintdef(oid), conname, conkey, conincluding FROM
pg_constraint WHERE conrelid = 'tbl'::regclass::oid;
+SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE
conrelid = 'tbl'::regclass::oid;
-- ensure that constraint works
INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS
x;
INSERT INTO tbl SELECT x, 2*x, NULL, NULL FROM generate_series(1,10) AS x;
--
2.11.0