aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/analyze.c26
-rw-r--r--src/backend/parser/parse_clause.c23
-rw-r--r--src/backend/parser/parse_coerce.c37
-rw-r--r--src/backend/parser/parse_func.c8
-rw-r--r--src/include/parser/parse_coerce.h2
5 files changed, 57 insertions, 39 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index c159fb2957b..98a83db8b5c 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -1434,9 +1434,8 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
for (i = 0; i < sublist_length; i++)
{
Oid coltype;
- int32 coltypmod = -1;
+ int32 coltypmod;
Oid colcoll;
- bool first = true;
coltype = select_common_type(pstate, colexprs[i], "VALUES", NULL);
@@ -1446,19 +1445,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
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;
- }
}
+ coltypmod = select_common_typmod(pstate, colexprs[i], coltype);
colcoll = select_common_collation(pstate, colexprs[i], true);
coltypes = lappend_oid(coltypes, coltype);
@@ -2020,8 +2009,6 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
Node *rcolnode = (Node *) rtle->expr;
Oid lcoltype = exprType(lcolnode);
Oid rcoltype = exprType(rcolnode);
- int32 lcoltypmod = exprTypmod(lcolnode);
- int32 rcoltypmod = exprTypmod(rcolnode);
Node *bestexpr;
int bestlocation;
Oid rescoltype;
@@ -2034,11 +2021,6 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
context,
&bestexpr);
bestlocation = exprLocation(bestexpr);
- /* if same type and same typmod, use typmod; else default */
- if (lcoltype == rcoltype && lcoltypmod == rcoltypmod)
- rescoltypmod = lcoltypmod;
- else
- rescoltypmod = -1;
/*
* Verify the coercions are actually possible. If not, we'd fail
@@ -2089,6 +2071,10 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
rtle->expr = (Expr *) rcolnode;
}
+ rescoltypmod = select_common_typmod(pstate,
+ list_make2(lcolnode, rcolnode),
+ rescoltype);
+
/*
* Select common collation. A common collation is required for
* all set operators except UNION ALL; see SQL:2008 7.13 <query
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index edcaf276c0a..7460e611604 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -1568,24 +1568,13 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
*r_node,
*res_node;
- /*
- * Choose output type if input types are dissimilar.
- */
- outcoltype = l_colvar->vartype;
- outcoltypmod = l_colvar->vartypmod;
- if (outcoltype != r_colvar->vartype)
- {
- outcoltype = select_common_type(pstate,
+ outcoltype = select_common_type(pstate,
+ list_make2(l_colvar, r_colvar),
+ "JOIN/USING",
+ NULL);
+ outcoltypmod = select_common_typmod(pstate,
list_make2(l_colvar, r_colvar),
- "JOIN/USING",
- NULL);
- outcoltypmod = -1; /* ie, unknown */
- }
- else if (outcoltypmod != r_colvar->vartypmod)
- {
- /* same type, but not same typmod */
- outcoltypmod = -1; /* ie, unknown */
- }
+ outcoltype);
/*
* Insert coercion functions if needed. Note that a difference in typmod
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 2ffe47026b9..a2924e3d1ce 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -1523,6 +1523,43 @@ coerce_to_common_type(ParseState *pstate, Node *node,
}
/*
+ * select_common_typmod()
+ * Determine the common typmod of a list of input expressions.
+ *
+ * common_type is the selected common type of the expressions, typically
+ * computed using select_common_type().
+ */
+int32
+select_common_typmod(ParseState *pstate, List *exprs, Oid common_type)
+{
+ ListCell *lc;
+ bool first = true;
+ int32 result = -1;
+
+ foreach(lc, exprs)
+ {
+ Node *expr = (Node *) lfirst(lc);
+
+ /* Types must match */
+ if (exprType(expr) != common_type)
+ return -1;
+ else if (first)
+ {
+ result = exprTypmod(expr);
+ first = false;
+ }
+ else
+ {
+ /* As soon as we see a non-matching typmod, fall back to -1 */
+ if (result != exprTypmod(expr))
+ return -1;
+ }
+ }
+
+ return result;
+}
+
+/*
* check_generic_type_consistency()
* Are the actual arguments potentially compatible with a
* polymorphic function?
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 9c3b6ad9166..a7a31704fb4 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -1750,6 +1750,7 @@ unify_hypothetical_args(ParseState *pstate,
ListCell *harg = list_nth_cell(fargs, hargpos);
ListCell *aarg = list_nth_cell(fargs, aargpos);
Oid commontype;
+ int32 commontypmod;
/* A mismatch means AggregateCreate didn't check properly ... */
if (declared_arg_types[hargpos] != declared_arg_types[aargpos])
@@ -1768,6 +1769,9 @@ unify_hypothetical_args(ParseState *pstate,
list_make2(lfirst(aarg), lfirst(harg)),
"WITHIN GROUP",
NULL);
+ commontypmod = select_common_typmod(pstate,
+ list_make2(lfirst(aarg), lfirst(harg)),
+ commontype);
/*
* Perform the coercions. We don't need to worry about NamedArgExprs
@@ -1776,7 +1780,7 @@ unify_hypothetical_args(ParseState *pstate,
lfirst(harg) = coerce_type(pstate,
(Node *) lfirst(harg),
actual_arg_types[hargpos],
- commontype, -1,
+ commontype, commontypmod,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
-1);
@@ -1784,7 +1788,7 @@ unify_hypothetical_args(ParseState *pstate,
lfirst(aarg) = coerce_type(pstate,
(Node *) lfirst(aarg),
actual_arg_types[aargpos],
- commontype, -1,
+ commontype, commontypmod,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
-1);
diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h
index 8686eaacbc9..33d7cfc8b64 100644
--- a/src/include/parser/parse_coerce.h
+++ b/src/include/parser/parse_coerce.h
@@ -71,6 +71,8 @@ extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
Oid targetTypeId,
const char *context);
+extern int32 select_common_typmod(ParseState *pstate, List *exprs, Oid common_type);
+
extern bool check_generic_type_consistency(const Oid *actual_arg_types,
const Oid *declared_arg_types,
int nargs);