From 028e3da2949482fa56f3ffdbda840782f2953b0b Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 19 Jul 2018 13:48:05 -0400 Subject: [PATCH] Fix pg_get_indexdef()'s behavior for included index columns. The multi-argument form of pg_get_indexdef() failed to print anything when asked to print a single index column that is an included column rather than a key column. This seems an unintentional result of someone having tried to take a short-cut and use the attrsOnly flag for two different purposes. To fix, split said flag into two flags, attrsOnly which suppresses non-attribute info, and keysOnly which suppresses included columns. Add a test case using psql's \d command, which relies on that function. (It's mighty tempting at this point to replace pg_get_indexdef_worker's mess of boolean flag arguments with a single bitmask-of-flags argument, which would allow making the call sites much more self-documenting. But I refrained for the moment.) Discussion: https://postgr.es/m/21724.1531943735@sss.pgh.pa.us --- src/backend/utils/adt/ruleutils.c | 45 +++++++++++-------- src/test/regress/expected/index_including.out | 10 +++++ src/test/regress/sql/index_including.sql | 1 + 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 065238b0fe..a38aed2065 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -320,7 +320,8 @@ static void decompile_column_index_array(Datum column_index_array, Oid relId, static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags); static char *pg_get_indexdef_worker(Oid indexrelid, int colno, const Oid *excludeOps, - bool attrsOnly, bool showTblSpc, bool inherits, + bool attrsOnly, bool keysOnly, + bool showTblSpc, bool inherits, int prettyFlags, bool missing_ok); static char *pg_get_statisticsobj_worker(Oid statextid, bool missing_ok); static char *pg_get_partkeydef_worker(Oid relid, int prettyFlags, @@ -1097,7 +1098,9 @@ pg_get_indexdef(PG_FUNCTION_ARGS) prettyFlags = PRETTYFLAG_INDENT; - res = pg_get_indexdef_worker(indexrelid, 0, NULL, false, false, false, + res = pg_get_indexdef_worker(indexrelid, 0, NULL, + false, false, + false, false, prettyFlags, true); if (res == NULL) @@ -1117,8 +1120,10 @@ pg_get_indexdef_ext(PG_FUNCTION_ARGS) prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; - res = pg_get_indexdef_worker(indexrelid, colno, NULL, colno != 0, false, - false, prettyFlags, true); + res = pg_get_indexdef_worker(indexrelid, colno, NULL, + colno != 0, false, + false, false, + prettyFlags, true); if (res == NULL) PG_RETURN_NULL(); @@ -1134,10 +1139,13 @@ pg_get_indexdef_ext(PG_FUNCTION_ARGS) char * pg_get_indexdef_string(Oid indexrelid) { - return pg_get_indexdef_worker(indexrelid, 0, NULL, false, true, true, 0, false); + return pg_get_indexdef_worker(indexrelid, 0, NULL, + false, false, + true, true, + 0, false); } -/* Internal version that just reports the column definitions */ +/* Internal version that just reports the key-column definitions */ char * pg_get_indexdef_columns(Oid indexrelid, bool pretty) { @@ -1145,7 +1153,9 @@ pg_get_indexdef_columns(Oid indexrelid, bool pretty) prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; - return pg_get_indexdef_worker(indexrelid, 0, NULL, true, false, false, + return pg_get_indexdef_worker(indexrelid, 0, NULL, + true, true, + false, false, prettyFlags, false); } @@ -1158,7 +1168,8 @@ pg_get_indexdef_columns(Oid indexrelid, bool pretty) static char * pg_get_indexdef_worker(Oid indexrelid, int colno, const Oid *excludeOps, - bool attrsOnly, bool showTblSpc, bool inherits, + bool attrsOnly, bool keysOnly, + bool showTblSpc, bool inherits, int prettyFlags, bool missing_ok) { /* might want a separate isConstraint parameter later */ @@ -1297,15 +1308,13 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, Oid keycolcollation; /* - * attrsOnly flag is used for building unique-constraint and - * exclusion-constraint error messages. Included attrs are meaningless - * there, so do not include them in the message. + * Ignore non-key attributes if told to. */ - if (attrsOnly && keyno >= idxrec->indnkeyatts) + if (keysOnly && keyno >= idxrec->indnkeyatts) break; - /* Report the INCLUDED attributes, if any. */ - if ((!attrsOnly) && keyno == idxrec->indnkeyatts) + /* Otherwise, print INCLUDE to divide key and non-key attrs. */ + if (!colno && keyno == idxrec->indnkeyatts) { appendStringInfoString(&buf, ") INCLUDE ("); sep = ""; @@ -1352,13 +1361,12 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, keycolcollation = exprCollation(indexkey); } - if (!attrsOnly && (!colno || colno == keyno + 1)) + /* Print additional decoration for (selected) key columns */ + if (!attrsOnly && keyno < idxrec->indnkeyatts && + (!colno || colno == keyno + 1)) { Oid indcoll; - if (keyno >= idxrec->indnkeyatts) - continue; - /* Add collation, if not default for column */ indcoll = indcollation->values[keyno]; if (OidIsValid(indcoll) && indcoll != keycolcollation) @@ -2197,6 +2205,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, false, false, false, + false, prettyFlags, false)); break; diff --git a/src/test/regress/expected/index_including.out b/src/test/regress/expected/index_including.out index 48bec3bf77..e2596391b1 100644 --- a/src/test/regress/expected/index_including.out +++ b/src/test/regress/expected/index_including.out @@ -19,6 +19,16 @@ WHERE i.indrelid = 'tbl_include_reg'::regclass ORDER BY c.relname; CREATE INDEX tbl_include_reg_idx ON public.tbl_include_reg USING btree (c1, c2) INCLUDE (c3, c4) (2 rows) +\d tbl_include_reg_idx +Index "public.tbl_include_reg_idx" + Column | Type | Definition +--------+---------+------------ + c1 | integer | c1 + c2 | integer | c2 + c3 | integer | c3 + c4 | box | c4 +btree, for table "public.tbl_include_reg" + -- Unique index and unique constraint CREATE TABLE tbl_include_unique1 (c1 int, c2 int, c3 int, c4 box); INSERT INTO tbl_include_unique1 SELECT x, 2*x, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x; diff --git a/src/test/regress/sql/index_including.sql b/src/test/regress/sql/index_including.sql index 2d833fc9f7..ee9d9f6bae 100644 --- a/src/test/regress/sql/index_including.sql +++ b/src/test/regress/sql/index_including.sql @@ -14,6 +14,7 @@ CREATE INDEX ON tbl_include_reg (c1, c2) INCLUDE (c1, c3); SELECT pg_get_indexdef(i.indexrelid) FROM pg_index i JOIN pg_class c ON i.indexrelid = c.oid WHERE i.indrelid = 'tbl_include_reg'::regclass ORDER BY c.relname; +\d tbl_include_reg_idx -- Unique index and unique constraint CREATE TABLE tbl_include_unique1 (c1 int, c2 int, c3 int, c4 box); -- 2.40.0