Attached is a patch that fixes this by storing typmod info in the RTE.
This turned out to be straightforward, and I think it's definitely
what we should do in HEAD. I have mixed emotions about whether it's
worth doing anything about it in the back branches.
I chose to redefine the existing coltypes/coltypmods/colcollations
lists for CTE RTEs as also applying to VALUES RTEs. That saves a
little space in the RangeTblEntry nodes and allows sharing code
in a couple of places. It's tempting to consider making that apply
to all RTE types, which would permit collapsing expandRTE() and
get_rte_attribute_type() into a single case. But AFAICS there would
be no benefit elsewhere, so I'm not sure the extra code churn is
justified.
BTW, I noticed that the CTE case of expandRTE() fails to assign the
specified location to the generated Vars, which is clearly a bug
though a very minor one; it would result in failing to display a
parse error location in some cases where we would do so for Vars from
other RTE types. That part might be worth back-patching, not sure.
regards, tom lane
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index e30c57e..d973225 100644
*** a/src/backend/nodes/copyfuncs.c
--- b/src/backend/nodes/copyfuncs.c
*************** _copyRangeTblEntry(const RangeTblEntry *
*** 2149,2161 ****
COPY_NODE_FIELD(functions);
COPY_SCALAR_FIELD(funcordinality);
COPY_NODE_FIELD(values_lists);
- COPY_NODE_FIELD(values_collations);
COPY_STRING_FIELD(ctename);
COPY_SCALAR_FIELD(ctelevelsup);
COPY_SCALAR_FIELD(self_reference);
! COPY_NODE_FIELD(ctecoltypes);
! COPY_NODE_FIELD(ctecoltypmods);
! COPY_NODE_FIELD(ctecolcollations);
COPY_NODE_FIELD(alias);
COPY_NODE_FIELD(eref);
COPY_SCALAR_FIELD(lateral);
--- 2149,2160 ----
COPY_NODE_FIELD(functions);
COPY_SCALAR_FIELD(funcordinality);
COPY_NODE_FIELD(values_lists);
COPY_STRING_FIELD(ctename);
COPY_SCALAR_FIELD(ctelevelsup);
COPY_SCALAR_FIELD(self_reference);
! COPY_NODE_FIELD(coltypes);
! COPY_NODE_FIELD(coltypmods);
! COPY_NODE_FIELD(colcollations);
COPY_NODE_FIELD(alias);
COPY_NODE_FIELD(eref);
COPY_SCALAR_FIELD(lateral);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index b7a109c..edc1797 100644
*** a/src/backend/nodes/equalfuncs.c
--- b/src/backend/nodes/equalfuncs.c
*************** _equalRangeTblEntry(const RangeTblEntry
*** 2460,2472 ****
COMPARE_NODE_FIELD(functions);
COMPARE_SCALAR_FIELD(funcordinality);
COMPARE_NODE_FIELD(values_lists);
- COMPARE_NODE_FIELD(values_collations);
COMPARE_STRING_FIELD(ctename);
COMPARE_SCALAR_FIELD(ctelevelsup);
COMPARE_SCALAR_FIELD(self_reference);
! COMPARE_NODE_FIELD(ctecoltypes);
! COMPARE_NODE_FIELD(ctecoltypmods);
! COMPARE_NODE_FIELD(ctecolcollations);
COMPARE_NODE_FIELD(alias);
COMPARE_NODE_FIELD(eref);
COMPARE_SCALAR_FIELD(lateral);
--- 2460,2471 ----
COMPARE_NODE_FIELD(functions);
COMPARE_SCALAR_FIELD(funcordinality);
COMPARE_NODE_FIELD(values_lists);
COMPARE_STRING_FIELD(ctename);
COMPARE_SCALAR_FIELD(ctelevelsup);
COMPARE_SCALAR_FIELD(self_reference);
! COMPARE_NODE_FIELD(coltypes);
! COMPARE_NODE_FIELD(coltypmods);
! COMPARE_NODE_FIELD(colcollations);
COMPARE_NODE_FIELD(alias);
COMPARE_NODE_FIELD(eref);
COMPARE_SCALAR_FIELD(lateral);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 0d858f5..7258c03 100644
*** a/src/backend/nodes/outfuncs.c
--- b/src/backend/nodes/outfuncs.c
*************** _outRangeTblEntry(StringInfo str, const
*** 2841,2855 ****
break;
case RTE_VALUES:
WRITE_NODE_FIELD(values_lists);
! WRITE_NODE_FIELD(values_collations);
break;
case RTE_CTE:
WRITE_STRING_FIELD(ctename);
WRITE_UINT_FIELD(ctelevelsup);
WRITE_BOOL_FIELD(self_reference);
! WRITE_NODE_FIELD(ctecoltypes);
! WRITE_NODE_FIELD(ctecoltypmods);
! WRITE_NODE_FIELD(ctecolcollations);
break;
default:
elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind);
--- 2841,2857 ----
break;
case RTE_VALUES:
WRITE_NODE_FIELD(values_lists);
! WRITE_NODE_FIELD(coltypes);
! WRITE_NODE_FIELD(coltypmods);
! WRITE_NODE_FIELD(colcollations);
break;
case RTE_CTE:
WRITE_STRING_FIELD(ctename);
WRITE_UINT_FIELD(ctelevelsup);
WRITE_BOOL_FIELD(self_reference);
! WRITE_NODE_FIELD(coltypes);
! WRITE_NODE_FIELD(coltypmods);
! WRITE_NODE_FIELD(colcollations);
break;
default:
elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind);
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index c587d4e..d608530 100644
*** a/src/backend/nodes/readfuncs.c
--- b/src/backend/nodes/readfuncs.c
*************** _readRangeTblEntry(void)
*** 1314,1328 ****
break;
case RTE_VALUES:
READ_NODE_FIELD(values_lists);
! READ_NODE_FIELD(values_collations);
break;
case RTE_CTE:
READ_STRING_FIELD(ctename);
READ_UINT_FIELD(ctelevelsup);
READ_BOOL_FIELD(self_reference);
! READ_NODE_FIELD(ctecoltypes);
! READ_NODE_FIELD(ctecoltypmods);
! READ_NODE_FIELD(ctecolcollations);
break;
default:
elog(ERROR, "unrecognized RTE kind: %d",
--- 1314,1330 ----
break;
case RTE_VALUES:
READ_NODE_FIELD(values_lists);
! READ_NODE_FIELD(coltypes);
! READ_NODE_FIELD(coltypmods);
! READ_NODE_FIELD(colcollations);
break;
case RTE_CTE:
READ_STRING_FIELD(ctename);
READ_UINT_FIELD(ctelevelsup);
READ_BOOL_FIELD(self_reference);
! READ_NODE_FIELD(coltypes);
! READ_NODE_FIELD(coltypmods);
! READ_NODE_FIELD(colcollations);
break;
default:
elog(ERROR, "unrecognized RTE kind: %d",
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index d91bc3b..2fe1c8c 100644
*** a/src/backend/optimizer/plan/setrefs.c
--- b/src/backend/optimizer/plan/setrefs.c
*************** add_rte_to_flat_rtable(PlannerGlobal *gl
*** 396,405 ****
newrte->joinaliasvars = NIL;
newrte->functions = NIL;
newrte->values_lists = NIL;
! newrte->values_collations = NIL;
! newrte->ctecoltypes = NIL;
! newrte->ctecoltypmods = NIL;
! newrte->ctecolcollations = NIL;
newrte->securityQuals = NIL;
glob->finalrtable = lappend(glob->finalrtable, newrte);
--- 396,404 ----
newrte->joinaliasvars = NIL;
newrte->functions = NIL;
newrte->values_lists = NIL;
! newrte->coltypes = NIL;
! newrte->coltypmods = NIL;
! newrte->colcollations = NIL;
newrte->securityQuals = NIL;
glob->finalrtable = lappend(glob->finalrtable, newrte);
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 7364346..5e65fe7 100644
*** a/src/backend/parser/analyze.c
--- b/src/backend/parser/analyze.c
*************** transformInsertStmt(ParseState *pstate,
*** 633,642 ****
* RTE.
*/
List *exprsLists = NIL;
! List *collations = NIL;
int sublist_length = -1;
bool lateral = false;
- int i;
Assert(selectStmt->intoClause == NULL);
--- 633,643 ----
* RTE.
*/
List *exprsLists = NIL;
! List *coltypes = NIL;
! List *coltypmods = NIL;
! List *colcollations = NIL;
int sublist_length = -1;
bool lateral = false;
Assert(selectStmt->intoClause == NULL);
*************** transformInsertStmt(ParseState *pstate,
*** 703,713 ****
}
/*
! * Although we don't really need collation info, let's just make sure
! * we provide a correctly-sized list in the VALUES RTE.
*/
! for (i = 0; i < sublist_length; i++)
! collations = lappend_oid(collations, InvalidOid);
/*
* Ordinarily there can't be any current-level Vars in the expression
--- 704,723 ----
}
/*
! * Construct column type/typmod/collation lists for the VALUES RTE.
! * Every expression in each column has been coerced to the type/typmod
! * of the corresponding target column or subfield, so it's sufficient
! * to look at the exprType/exprTypmod of the first row. We don't care
! * about the collation labeling, so just fill in InvalidOid for that.
*/
! foreach(lc, (List *) linitial(exprsLists))
! {
! Node *val = (Node *) lfirst(lc);
!
! coltypes = lappend_oid(coltypes, exprType(val));
! coltypmods = lappend_int(coltypmods, exprTypmod(val));
! colcollations = lappend_oid(colcollations, InvalidOid);
! }
/*
* Ordinarily there can't be any current-level Vars in the expression
*************** transformInsertStmt(ParseState *pstate,
*** 722,728 ****
/*
* Generate the VALUES RTE
*/
! rte = addRangeTableEntryForValues(pstate, exprsLists, collations,
NULL, lateral, true);
rtr = makeNode(RangeTblRef);
/* assume new rte is at end */
--- 732,739 ----
/*
* Generate the VALUES RTE
*/
! rte = addRangeTableEntryForValues(pstate, exprsLists,
! coltypes, coltypmods, colcollations,
NULL, lateral, true);
rtr = makeNode(RangeTblRef);
/* assume new rte is at end */
*************** transformValuesClause(ParseState *pstate
*** 1274,1280 ****
{
Query *qry = makeNode(Query);
List *exprsLists;
! List *collations;
List **colexprs = NULL;
int sublist_length = -1;
bool lateral = false;
--- 1285,1293 ----
{
Query *qry = makeNode(Query);
List *exprsLists;
! List *coltypes = NIL;
! List *coltypmods = NIL;
! List *colcollations = NIL;
List **colexprs = NULL;
int sublist_length = -1;
bool lateral = false;
*************** transformValuesClause(ParseState *pstate
*** 1360,1367 ****
/*
* Now resolve the common types of the columns, and coerce everything to
! * those types. Then identify the common collation, if any, of each
! * column.
*
* We must do collation processing now because (1) assign_query_collations
* doesn't process rangetable entries, and (2) we need to label the VALUES
--- 1373,1380 ----
/*
* Now resolve the common types of the columns, and coerce everything to
! * those types. Then identify the common typmod and common collation, if
! * any, of each column.
*
* We must do collation processing now because (1) assign_query_collations
* doesn't process rangetable entries, and (2) we need to label the VALUES
*************** transformValuesClause(ParseState *pstate
*** 1372,1382 ****
*
* Note we modify the per-column expression lists in-place.
*/
- collations = NIL;
for (i = 0; i < sublist_length; i++)
{
Oid coltype;
Oid colcoll;
coltype = select_common_type(pstate, colexprs[i], "VALUES", NULL);
--- 1385,1396 ----
*
* Note we modify the per-column expression lists in-place.
*/
for (i = 0; i < sublist_length; i++)
{
Oid coltype;
+ int32 coltypmod = -1;
Oid colcoll;
+ bool first = true;
coltype = select_common_type(pstate, colexprs[i], "VALUES", NULL);
*************** transformValuesClause(ParseState *pstate
*** 1386,1396 ****
col = coerce_to_common_type(pstate, col, coltype, "VALUES");
lfirst(lc) = (void *) col;
}
colcoll = select_common_collation(pstate, colexprs[i], true);
! collations = lappend_oid(collations, colcoll);
}
/*
--- 1400,1423 ----
col = coerce_to_common_type(pstate, col, coltype, "VALUES");
lfirst(lc) = (void *) col;
+ if (first)
+ {
+ coltypmod = exprTypmod(col);
+ first = false;
+ }
+ else
+ {
+ /* As soon as we see a non-matching typmod, fall back to -1 */
+ if (coltypmod >= 0 && coltypmod != exprTypmod(col))
+ coltypmod = -1;
+ }
}
colcoll = select_common_collation(pstate, colexprs[i], true);
! coltypes = lappend_oid(coltypes, coltype);
! coltypmods = lappend_int(coltypmods, coltypmod);
! colcollations = lappend_oid(colcollations, colcoll);
}
/*
*************** transformValuesClause(ParseState *pstate
*** 1432,1438 ****
/*
* Generate the VALUES RTE
*/
! rte = addRangeTableEntryForValues(pstate, exprsLists, collations,
NULL, lateral, true);
addRTEtoQuery(pstate, rte, true, true, true);
--- 1459,1466 ----
/*
* Generate the VALUES RTE
*/
! rte = addRangeTableEntryForValues(pstate, exprsLists,
! coltypes, coltypmods, colcollations,
NULL, lateral, true);
addRTEtoQuery(pstate, rte, true, true, true);
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 1e3ecbc..58f7050 100644
*** a/src/backend/parser/parse_relation.c
--- b/src/backend/parser/parse_relation.c
*************** addRangeTableEntryForFunction(ParseState
*** 1635,1641 ****
RangeTblEntry *
addRangeTableEntryForValues(ParseState *pstate,
List *exprs,
! List *collations,
Alias *alias,
bool lateral,
bool inFromCl)
--- 1635,1643 ----
RangeTblEntry *
addRangeTableEntryForValues(ParseState *pstate,
List *exprs,
! List *coltypes,
! List *coltypmods,
! List *colcollations,
Alias *alias,
bool lateral,
bool inFromCl)
*************** addRangeTableEntryForValues(ParseState *
*** 1652,1658 ****
rte->relid = InvalidOid;
rte->subquery = NULL;
rte->values_lists = exprs;
! rte->values_collations = collations;
rte->alias = alias;
eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
--- 1654,1662 ----
rte->relid = InvalidOid;
rte->subquery = NULL;
rte->values_lists = exprs;
! rte->coltypes = coltypes;
! rte->coltypmods = coltypmods;
! rte->colcollations = colcollations;
rte->alias = alias;
eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
*************** addRangeTableEntryForCTE(ParseState *pst
*** 1822,1830 ****
parser_errposition(pstate, rv->location)));
}
! rte->ctecoltypes = cte->ctecoltypes;
! rte->ctecoltypmods = cte->ctecoltypmods;
! rte->ctecolcollations = cte->ctecolcollations;
rte->alias = alias;
if (alias)
--- 1826,1834 ----
parser_errposition(pstate, rv->location)));
}
! rte->coltypes = cte->ctecoltypes;
! rte->coltypmods = cte->ctecoltypmods;
! rte->colcollations = cte->ctecolcollations;
rte->alias = alias;
if (alias)
*************** expandRTE(RangeTblEntry *rte, int rtinde
*** 2153,2198 ****
}
}
break;
- case RTE_VALUES:
- {
- /* Values RTE */
- ListCell *aliasp_item = list_head(rte->eref->colnames);
- ListCell *lcv;
- ListCell *lcc;
-
- varattno = 0;
- forboth(lcv, (List *) linitial(rte->values_lists),
- lcc, rte->values_collations)
- {
- Node *col = (Node *) lfirst(lcv);
- Oid colcollation = lfirst_oid(lcc);
-
- varattno++;
- if (colnames)
- {
- /* Assume there is one alias per column */
- char *label = strVal(lfirst(aliasp_item));
-
- *colnames = lappend(*colnames,
- makeString(pstrdup(label)));
- aliasp_item = lnext(aliasp_item);
- }
-
- if (colvars)
- {
- Var *varnode;
-
- varnode = makeVar(rtindex, varattno,
- exprType(col),
- exprTypmod(col),
- colcollation,
- sublevels_up);
- varnode->location = location;
- *colvars = lappend(*colvars, varnode);
- }
- }
- }
- break;
case RTE_JOIN:
{
/* Join RTE */
--- 2157,2162 ----
*************** expandRTE(RangeTblEntry *rte, int rtinde
*** 2262,2278 ****
}
}
break;
case RTE_CTE:
{
ListCell *aliasp_item = list_head(rte->eref->colnames);
ListCell *lct;
ListCell *lcm;
ListCell *lcc;
varattno = 0;
! forthree(lct, rte->ctecoltypes,
! lcm, rte->ctecoltypmods,
! lcc, rte->ctecolcollations)
{
Oid coltype = lfirst_oid(lct);
int32 coltypmod = lfirst_int(lcm);
--- 2226,2244 ----
}
}
break;
+ case RTE_VALUES:
case RTE_CTE:
{
+ /* Values or CTE RTE */
ListCell *aliasp_item = list_head(rte->eref->colnames);
ListCell *lct;
ListCell *lcm;
ListCell *lcc;
varattno = 0;
! forthree(lct, rte->coltypes,
! lcm, rte->coltypmods,
! lcc, rte->colcollations)
{
Oid coltype = lfirst_oid(lct);
int32 coltypmod = lfirst_int(lcm);
*************** expandRTE(RangeTblEntry *rte, int rtinde
*** 2285,2291 ****
/* Assume there is one alias per output column */
char *label = strVal(lfirst(aliasp_item));
! *colnames = lappend(*colnames, makeString(pstrdup(label)));
aliasp_item = lnext(aliasp_item);
}
--- 2251,2258 ----
/* Assume there is one alias per output column */
char *label = strVal(lfirst(aliasp_item));
! *colnames = lappend(*colnames,
! makeString(pstrdup(label)));
aliasp_item = lnext(aliasp_item);
}
*************** expandRTE(RangeTblEntry *rte, int rtinde
*** 2296,2301 ****
--- 2263,2270 ----
varnode = makeVar(rtindex, varattno,
coltype, coltypmod, colcoll,
sublevels_up);
+ varnode->location = location;
+
*colvars = lappend(*colvars, varnode);
}
}
*************** get_rte_attribute_type(RangeTblEntry *rt
*** 2654,2675 ****
rte->eref->aliasname)));
}
break;
- case RTE_VALUES:
- {
- /* Values RTE --- get type info from first sublist */
- /* collation is stored separately, though */
- List *collist = (List *) linitial(rte->values_lists);
- Node *col;
-
- if (attnum < 1 || attnum > list_length(collist))
- elog(ERROR, "values list %s does not have attribute %d",
- rte->eref->aliasname, attnum);
- col = (Node *) list_nth(collist, attnum - 1);
- *vartype = exprType(col);
- *vartypmod = exprTypmod(col);
- *varcollid = list_nth_oid(rte->values_collations, attnum - 1);
- }
- break;
case RTE_JOIN:
{
/*
--- 2623,2628 ----
*************** get_rte_attribute_type(RangeTblEntry *rt
*** 2685,2697 ****
*varcollid = exprCollation(aliasvar);
}
break;
case RTE_CTE:
{
! /* CTE RTE --- get type info from lists in the RTE */
! Assert(attnum > 0 && attnum <= list_length(rte->ctecoltypes));
! *vartype = list_nth_oid(rte->ctecoltypes, attnum - 1);
! *vartypmod = list_nth_int(rte->ctecoltypmods, attnum - 1);
! *varcollid = list_nth_oid(rte->ctecolcollations, attnum - 1);
}
break;
default:
--- 2638,2651 ----
*varcollid = exprCollation(aliasvar);
}
break;
+ case RTE_VALUES:
case RTE_CTE:
{
! /* VALUES or CTE RTE --- get type info from lists in the RTE */
! Assert(attnum > 0 && attnum <= list_length(rte->coltypes));
! *vartype = list_nth_oid(rte->coltypes, attnum - 1);
! *vartypmod = list_nth_int(rte->coltypmods, attnum - 1);
! *varcollid = list_nth_oid(rte->colcollations, attnum - 1);
}
break;
default:
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 6b95c48..fc532fb 100644
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
*************** typedef struct RangeTblEntry
*** 927,933 ****
* 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):
--- 927,932 ----
*************** typedef struct RangeTblEntry
*** 935,943 ****
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 in all RTEs:
--- 934,950 ----
char *ctename; /* name of the WITH list item */
Index ctelevelsup; /* number of query levels up */
bool self_reference; /* is this a recursive self-reference? */
!
! /*
! * 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:
diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h
index 3ef3d7b..9463f9d 100644
*** a/src/include/parser/parse_relation.h
--- b/src/include/parser/parse_relation.h
*************** extern RangeTblEntry *addRangeTableEntry
*** 85,91 ****
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForValues(ParseState *pstate,
List *exprs,
! List *collations,
Alias *alias,
bool lateral,
bool inFromCl);
--- 85,93 ----
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForValues(ParseState *pstate,
List *exprs,
! List *coltypes,
! List *coltypmods,
! List *colcollations,
Alias *alias,
bool lateral,
bool inFromCl);
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index 66ed2c8..15ceefe 100644
*** a/src/test/regress/expected/create_view.out
--- b/src/test/regress/expected/create_view.out
*************** SELECT relname, relkind, reloptions FROM
*** 288,293 ****
--- 288,317 ----
mysecview4 | v | {security_barrier=false}
(4 rows)
+ -- This test checks that proper typmods are assigned in a multi-row VALUES
+ CREATE TABLE tt1 AS
+ SELECT * FROM (
+ VALUES
+ ('abc'::varchar(3), '0123456789', 42, 'abcd'::varchar(4)),
+ ('0123456789', 'abc'::varchar(3), 42.12, 'abc'::varchar(4))
+ ) vv(a,b,c,d);
+ \d tt1
+ Table "testviewschm2.tt1"
+ Column | Type | Collation | Nullable | Default
+ --------+----------------------+-----------+----------+---------
+ a | character varying | | |
+ b | character varying | | |
+ c | numeric | | |
+ d | character varying(4) | | |
+
+ SELECT * FROM tt1;
+ a | b | c | d
+ ------------+------------+-------+------
+ abc | 0123456789 | 42 | abcd
+ 0123456789 | abc | 42.12 | abc
+ (2 rows)
+
+ DROP TABLE tt1;
-- Test view decompilation in the face of relation renaming conflicts
CREATE TABLE tt1 (f1 int, f2 int, f3 text);
CREATE TABLE tx1 (x1 int, x2 int, x3 text);
diff --git a/src/test/regress/sql/create_view.sql b/src/test/regress/sql/create_view.sql
index 8bed5a5..c3391f9 100644
*** a/src/test/regress/sql/create_view.sql
--- b/src/test/regress/sql/create_view.sql
*************** SELECT relname, relkind, reloptions FROM
*** 224,229 ****
--- 224,241 ----
'mysecview3'::regclass, 'mysecview4'::regclass)
ORDER BY relname;
+ -- This test checks that proper typmods are assigned in a multi-row VALUES
+
+ CREATE TABLE tt1 AS
+ SELECT * FROM (
+ VALUES
+ ('abc'::varchar(3), '0123456789', 42, 'abcd'::varchar(4)),
+ ('0123456789', 'abc'::varchar(3), 42.12, 'abc'::varchar(4))
+ ) vv(a,b,c,d);
+ \d tt1
+ SELECT * FROM tt1;
+ DROP TABLE tt1;
+
-- Test view decompilation in the face of relation renaming conflicts
CREATE TABLE tt1 (f1 int, f2 int, f3 text);
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers