diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2016-12-08 11:40:02 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2016-12-08 11:40:02 -0500 |
commit | 0b78106cd4651ad7867036a463ec743f6d3d2e86 (patch) | |
tree | 76fca8c917ad661ee42fbd56ed609c77febb04b5 /src/include/nodes/parsenodes.h | |
parent | 2560d244b4c9fc08f1d076b3c40913bec5f7e31f (diff) | |
download | postgresql-0b78106cd4651ad7867036a463ec743f6d3d2e86.tar.gz postgresql-0b78106cd4651ad7867036a463ec743f6d3d2e86.zip |
Fix reporting of column typmods for multi-row VALUES constructs.
expandRTE() and get_rte_attribute_type() reported the exprType() and
exprTypmod() values of the expressions in the first row of the VALUES as
being the column type/typmod returned by the VALUES RTE. That's fine for
the data type, since we coerce all expressions in a column to have the same
common type. But we don't coerce them to have a common typmod, so it was
possible for rows after the first one to return values that violate the
claimed column typmod. This leads to the incorrect result seen in bug
#14448 from Hassan Mahmood, as well as some other corner-case misbehaviors.
The desired behavior is the same as we use in other type-unification
cases: report the common typmod if there is one, but otherwise return -1
indicating no particular constraint. It's cheap for transformValuesClause
to determine the common typmod while transforming a multi-row VALUES, but
it'd be less cheap for expandRTE() and get_rte_attribute_type() to
re-determine that info every time they're asked --- possibly a lot less
cheap, if the VALUES has many rows. Therefore, the best fix is to record
the common typmods explicitly in a list in the VALUES RTE, as we were
already doing for column collations. This looks quite a bit like what
we're doing for CTE RTEs, so we can save a little bit of space and code by
unifying the representation for those two RTE types. They both now share
coltypes/coltypmods/colcollations fields. (At some point it might seem
desirable to populate those fields for all RTE types; but right now it
looks like constructing them for other RTE types would add more code and
cycles than it would save.)
The RTE change requires a catversion bump, so this fix is only usable
in HEAD. If we fix this at all in the back branches, the patch will
need to look quite different.
Report: https://postgr.es/m/20161205143037.4377.60754@wrigleys.postgresql.org
Discussion: https://postgr.es/m/27429.1480968538@sss.pgh.pa.us
Diffstat (limited to 'src/include/nodes/parsenodes.h')
-rw-r--r-- | src/include/nodes/parsenodes.h | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 6b95c484476..fc532fbd432 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -927,7 +927,6 @@ typedef struct RangeTblEntry * Fields valid for a values RTE (else NIL): */ List *values_lists; /* list of expression lists */ - List *values_collations; /* OID list of column collation OIDs */ /* * Fields valid for a CTE RTE (else NULL/zero): @@ -935,9 +934,17 @@ typedef struct RangeTblEntry char *ctename; /* name of the WITH list item */ Index ctelevelsup; /* number of query levels up */ bool self_reference; /* is this a recursive self-reference? */ - List *ctecoltypes; /* OID list of column type OIDs */ - List *ctecoltypmods; /* integer list of column typmods */ - List *ctecolcollations; /* OID list of column collation OIDs */ + + /* + * Fields valid for values and CTE RTEs (else NIL): + * + * We need these for CTE RTEs so that the types of self-referential + * columns are well-defined. For VALUES RTEs, storing these explicitly + * saves having to re-determine the info by scanning the values_lists. + */ + List *coltypes; /* OID list of column type OIDs */ + List *coltypmods; /* integer list of column typmods */ + List *colcollations; /* OID list of column collation OIDs */ /* * Fields valid in all RTEs: |