Fix error reporting for index expressions of prohibited types.
authorTom Lane <[email protected]>
Tue, 17 Dec 2019 22:44:27 +0000 (17:44 -0500)
committerTom Lane <[email protected]>
Tue, 17 Dec 2019 22:44:27 +0000 (17:44 -0500)
If CheckAttributeType() threw an error about the datatype of an
index expression column, it would report an empty column name,
which is pretty unhelpful and certainly not the intended behavior.
I (tgl) evidently broke this in commit cfc5008a5, by not noticing
that the column's attname was used above where I'd placed the
assignment of it.

In HEAD and v12, this is trivially fixable by moving up the
assignment of attname.  Before v12 the code is a bit more messy;
to avoid doing substantial refactoring, I took the lazy way out
and just put in two copies of the assignment code.

Report and patch by Amit Langote.  Back-patch to all supported
branches.

Discussion: https://postgr.es/m/CA+HiwqFA+BGyBFimjiYXXMa2Hc3fcL0+OJOyzUNjhU4NCa_XXw@mail.gmail.com

src/backend/catalog/index.c
src/test/regress/expected/create_index.out
src/test/regress/sql/create_index.sql

index e9955707fa7a6624cf7cdfed2bdf29623d6b1930..79439a0c66d97a0fa9750bdefdbb8e10a9b48b06 100644 (file)
@@ -312,6 +312,14 @@ ConstructTupleDescriptor(Relation heapRelation,
                to->attcollation = (i < numkeyatts) ?
                        collationObjectId[i] : InvalidOid;
 
+               /*
+                * Set the attribute name as specified by caller.
+                */
+               if (colnames_item == NULL)      /* shouldn't happen */
+                       elog(ERROR, "too few entries in colnames list");
+               namestrcpy(&to->attname, (const char *) lfirst(colnames_item));
+               colnames_item = lnext(indexColNames, colnames_item);
+
                /*
                 * For simple index columns, we copy some pg_attribute fields from the
                 * parent relation.  For expressions we have to look at the expression
@@ -329,7 +337,6 @@ ConstructTupleDescriptor(Relation heapRelation,
                        from = TupleDescAttr(heapTupDesc,
                                                                 AttrNumberGetAttrOffset(atnum));
 
-                       namecpy(&to->attname, &from->attname);
                        to->atttypid = from->atttypid;
                        to->attlen = from->attlen;
                        to->attndims = from->attndims;
@@ -390,14 +397,6 @@ ConstructTupleDescriptor(Relation heapRelation,
                 */
                to->attrelid = InvalidOid;
 
-               /*
-                * Set the attribute name as specified by caller.
-                */
-               if (colnames_item == NULL)      /* shouldn't happen */
-                       elog(ERROR, "too few entries in colnames list");
-               namestrcpy(&to->attname, (const char *) lfirst(colnames_item));
-               colnames_item = lnext(indexColNames, colnames_item);
-
                /*
                 * Check the opclass and index AM to see if either provides a keytype
                 * (overriding the attribute type).  Opclass (if exists) takes
index 645ae2cf343caefa556111833bd3402319273ce6..6446907a65bf4d81dab1a9757db2538f2b1acd60 100644 (file)
@@ -1281,6 +1281,23 @@ ERROR:  duplicate key value violates unique constraint "func_index_index"
 DETAIL:  Key (textcat(f1, f2))=(ABCDEF) already exists.
 -- but this shouldn't:
 INSERT INTO func_index_heap VALUES('QWERTY');
+-- while we're here, see that the metadata looks sane
+\d func_index_heap
+         Table "public.func_index_heap"
+ Column | Type | Collation | Nullable | Default 
+--------+------+-----------+----------+---------
+ f1     | text |           |          | 
+ f2     | text |           |          | 
+Indexes:
+    "func_index_index" UNIQUE, btree (textcat(f1, f2))
+
+\d func_index_index
+     Index "public.func_index_index"
+ Column  | Type | Key? |   Definition    
+---------+------+------+-----------------
+ textcat | text | yes  | textcat(f1, f2)
+unique, btree, for table "public.func_index_heap"
+
 --
 -- Same test, expressional index
 --
@@ -1296,6 +1313,26 @@ ERROR:  duplicate key value violates unique constraint "func_index_index"
 DETAIL:  Key ((f1 || f2))=(ABCDEF) already exists.
 -- but this shouldn't:
 INSERT INTO func_index_heap VALUES('QWERTY');
+-- while we're here, see that the metadata looks sane
+\d func_index_heap
+         Table "public.func_index_heap"
+ Column | Type | Collation | Nullable | Default 
+--------+------+-----------+----------+---------
+ f1     | text |           |          | 
+ f2     | text |           |          | 
+Indexes:
+    "func_index_index" UNIQUE, btree ((f1 || f2))
+
+\d func_index_index
+  Index "public.func_index_index"
+ Column | Type | Key? | Definition 
+--------+------+------+------------
+ expr   | text | yes  | (f1 || f2)
+unique, btree, for table "public.func_index_heap"
+
+-- this should fail because of unsafe column type (anonymous record)
+create index on func_index_heap ((f1 || f2), (row(f1, f2)));
+ERROR:  column "row" has pseudo-type record
 --
 -- Test unique index with included columns
 --
index 73a55ead4bf6d3abf02f84b150c5f5886d7d9211..3c0c1cdc5eccbfebf2789f29b72191e49c576a0f 100644 (file)
@@ -401,6 +401,10 @@ INSERT INTO func_index_heap VALUES('ABCD', 'EF');
 -- but this shouldn't:
 INSERT INTO func_index_heap VALUES('QWERTY');
 
+-- while we're here, see that the metadata looks sane
+\d func_index_heap
+\d func_index_index
+
 
 --
 -- Same test, expressional index
@@ -417,6 +421,14 @@ INSERT INTO func_index_heap VALUES('ABCD', 'EF');
 -- but this shouldn't:
 INSERT INTO func_index_heap VALUES('QWERTY');
 
+-- while we're here, see that the metadata looks sane
+\d func_index_heap
+\d func_index_index
+
+-- this should fail because of unsafe column type (anonymous record)
+create index on func_index_heap ((f1 || f2), (row(f1, f2)));
+
+
 --
 -- Test unique index with included columns
 --