Skip to content

Commit 81d13a8

Browse files
committed
Make contrib/tablefunc crosstab() also check typmod
contrib/tablefunc connectby() checks both type OID and typmod for its output columns while crosstab() only checks type OID. Fix that by makeing the crosstab() check look more like the connectby() check. Reported-by: Tom Lane Reviewed-by: Tom Lane Discussion: https://postgr.es/m/flat/18937.1709676295%40sss.pgh.pa.us
1 parent 5194431 commit 81d13a8

File tree

1 file changed

+19
-13
lines changed

1 file changed

+19
-13
lines changed

contrib/tablefunc/tablefunc.c

+19-13
Original file line numberDiff line numberDiff line change
@@ -1527,10 +1527,10 @@ static void
15271527
compatCrosstabTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc)
15281528
{
15291529
int i;
1530-
Form_pg_attribute ret_attr;
15311530
Oid ret_atttypid;
1532-
Form_pg_attribute sql_attr;
15331531
Oid sql_atttypid;
1532+
int32 ret_atttypmod;
1533+
int32 sql_atttypmod;
15341534

15351535
if (ret_tupdesc->natts < 2)
15361536
ereport(ERROR,
@@ -1539,34 +1539,40 @@ compatCrosstabTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc)
15391539
errdetail("Return row must have at least two columns.")));
15401540
Assert(sql_tupdesc->natts == 3); /* already checked by caller */
15411541

1542-
/* check the rowid types match */
1542+
/* check the row_name types match */
15431543
ret_atttypid = TupleDescAttr(ret_tupdesc, 0)->atttypid;
15441544
sql_atttypid = TupleDescAttr(sql_tupdesc, 0)->atttypid;
1545-
if (ret_atttypid != sql_atttypid)
1545+
ret_atttypmod = TupleDescAttr(ret_tupdesc, 0)->atttypmod;
1546+
sql_atttypmod = TupleDescAttr(sql_tupdesc, 0)->atttypmod;
1547+
if (ret_atttypid != sql_atttypid ||
1548+
(ret_atttypmod >= 0 && ret_atttypmod != sql_atttypmod))
15461549
ereport(ERROR,
15471550
(errcode(ERRCODE_DATATYPE_MISMATCH),
15481551
errmsg("invalid crosstab return type"),
15491552
errdetail("Source row_name datatype %s does not match return row_name datatype %s.",
1550-
format_type_be(sql_atttypid),
1551-
format_type_be(ret_atttypid))));
1553+
format_type_with_typemod(sql_atttypid, sql_atttypmod),
1554+
format_type_with_typemod(ret_atttypid, ret_atttypmod))));
15521555

15531556
/*
1554-
* - attribute [1] of the sql tuple is the category; no need to check it -
1555-
* attribute [2] of the sql tuple should match attributes [1] to [natts]
1557+
* attribute [1] of sql tuple is the category; no need to check it
1558+
* attribute [2] of sql tuple should match attributes [1] to [natts - 1]
15561559
* of the return tuple
15571560
*/
1558-
sql_attr = TupleDescAttr(sql_tupdesc, 2);
1561+
sql_atttypid = TupleDescAttr(sql_tupdesc, 2)->atttypid;
1562+
sql_atttypmod = TupleDescAttr(sql_tupdesc, 2)->atttypmod;
15591563
for (i = 1; i < ret_tupdesc->natts; i++)
15601564
{
1561-
ret_attr = TupleDescAttr(ret_tupdesc, i);
1565+
ret_atttypid = TupleDescAttr(ret_tupdesc, i)->atttypid;
1566+
ret_atttypmod = TupleDescAttr(ret_tupdesc, i)->atttypmod;
15621567

1563-
if (ret_attr->atttypid != sql_attr->atttypid)
1568+
if (ret_atttypid != sql_atttypid ||
1569+
(ret_atttypmod >= 0 && ret_atttypmod != sql_atttypmod))
15641570
ereport(ERROR,
15651571
(errcode(ERRCODE_DATATYPE_MISMATCH),
15661572
errmsg("invalid crosstab return type"),
15671573
errdetail("Source value datatype %s does not match return value datatype %s in column %d.",
1568-
format_type_be(sql_attr->atttypid),
1569-
format_type_be(ret_attr->atttypid),
1574+
format_type_with_typemod(sql_atttypid, sql_atttypmod),
1575+
format_type_with_typemod(ret_atttypid, ret_atttypmod),
15701576
i + 1)));
15711577
}
15721578

0 commit comments

Comments
 (0)