Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f893e68

Browse files
committed
Add select_common_typmod()
This accompanies select_common_type() and select_common_collation(). Typmods were previously combined using hand-coded logic in several places. The logic in select_common_typmod() isn't very exciting, but it makes the code more compact and readable in a few locations, and in the future we can perhaps do more complicated things if desired. As a small enhancement, the type unification of the direct and aggregate arguments of hypothetical-set aggregates now unifies the typmod as well using this new function, instead of just dropping it. Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi> Discussion: https://www.postgresql.org/message-id/flat/97df3af9-8b5e-fb7f-a029-3eb7e80d7af9@2ndquadrant.com
1 parent 59ab4ac commit f893e68

File tree

5 files changed

+57
-39
lines changed

5 files changed

+57
-39
lines changed

src/backend/parser/analyze.c

+6-20
Original file line numberDiff line numberDiff line change
@@ -1434,9 +1434,8 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
14341434
for (i = 0; i < sublist_length; i++)
14351435
{
14361436
Oid coltype;
1437-
int32 coltypmod = -1;
1437+
int32 coltypmod;
14381438
Oid colcoll;
1439-
bool first = true;
14401439

14411440
coltype = select_common_type(pstate, colexprs[i], "VALUES", NULL);
14421441

@@ -1446,19 +1445,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
14461445

14471446
col = coerce_to_common_type(pstate, col, coltype, "VALUES");
14481447
lfirst(lc) = (void *) col;
1449-
if (first)
1450-
{
1451-
coltypmod = exprTypmod(col);
1452-
first = false;
1453-
}
1454-
else
1455-
{
1456-
/* As soon as we see a non-matching typmod, fall back to -1 */
1457-
if (coltypmod >= 0 && coltypmod != exprTypmod(col))
1458-
coltypmod = -1;
1459-
}
14601448
}
14611449

1450+
coltypmod = select_common_typmod(pstate, colexprs[i], coltype);
14621451
colcoll = select_common_collation(pstate, colexprs[i], true);
14631452

14641453
coltypes = lappend_oid(coltypes, coltype);
@@ -2020,8 +2009,6 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
20202009
Node *rcolnode = (Node *) rtle->expr;
20212010
Oid lcoltype = exprType(lcolnode);
20222011
Oid rcoltype = exprType(rcolnode);
2023-
int32 lcoltypmod = exprTypmod(lcolnode);
2024-
int32 rcoltypmod = exprTypmod(rcolnode);
20252012
Node *bestexpr;
20262013
int bestlocation;
20272014
Oid rescoltype;
@@ -2034,11 +2021,6 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
20342021
context,
20352022
&bestexpr);
20362023
bestlocation = exprLocation(bestexpr);
2037-
/* if same type and same typmod, use typmod; else default */
2038-
if (lcoltype == rcoltype && lcoltypmod == rcoltypmod)
2039-
rescoltypmod = lcoltypmod;
2040-
else
2041-
rescoltypmod = -1;
20422024

20432025
/*
20442026
* Verify the coercions are actually possible. If not, we'd fail
@@ -2089,6 +2071,10 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
20892071
rtle->expr = (Expr *) rcolnode;
20902072
}
20912073

2074+
rescoltypmod = select_common_typmod(pstate,
2075+
list_make2(lcolnode, rcolnode),
2076+
rescoltype);
2077+
20922078
/*
20932079
* Select common collation. A common collation is required for
20942080
* all set operators except UNION ALL; see SQL:2008 7.13 <query

src/backend/parser/parse_clause.c

+6-17
Original file line numberDiff line numberDiff line change
@@ -1568,24 +1568,13 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
15681568
*r_node,
15691569
*res_node;
15701570

1571-
/*
1572-
* Choose output type if input types are dissimilar.
1573-
*/
1574-
outcoltype = l_colvar->vartype;
1575-
outcoltypmod = l_colvar->vartypmod;
1576-
if (outcoltype != r_colvar->vartype)
1577-
{
1578-
outcoltype = select_common_type(pstate,
1571+
outcoltype = select_common_type(pstate,
1572+
list_make2(l_colvar, r_colvar),
1573+
"JOIN/USING",
1574+
NULL);
1575+
outcoltypmod = select_common_typmod(pstate,
15791576
list_make2(l_colvar, r_colvar),
1580-
"JOIN/USING",
1581-
NULL);
1582-
outcoltypmod = -1; /* ie, unknown */
1583-
}
1584-
else if (outcoltypmod != r_colvar->vartypmod)
1585-
{
1586-
/* same type, but not same typmod */
1587-
outcoltypmod = -1; /* ie, unknown */
1588-
}
1577+
outcoltype);
15891578

15901579
/*
15911580
* Insert coercion functions if needed. Note that a difference in typmod

src/backend/parser/parse_coerce.c

+37
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,43 @@ coerce_to_common_type(ParseState *pstate, Node *node,
15221522
return node;
15231523
}
15241524

1525+
/*
1526+
* select_common_typmod()
1527+
* Determine the common typmod of a list of input expressions.
1528+
*
1529+
* common_type is the selected common type of the expressions, typically
1530+
* computed using select_common_type().
1531+
*/
1532+
int32
1533+
select_common_typmod(ParseState *pstate, List *exprs, Oid common_type)
1534+
{
1535+
ListCell *lc;
1536+
bool first = true;
1537+
int32 result = -1;
1538+
1539+
foreach(lc, exprs)
1540+
{
1541+
Node *expr = (Node *) lfirst(lc);
1542+
1543+
/* Types must match */
1544+
if (exprType(expr) != common_type)
1545+
return -1;
1546+
else if (first)
1547+
{
1548+
result = exprTypmod(expr);
1549+
first = false;
1550+
}
1551+
else
1552+
{
1553+
/* As soon as we see a non-matching typmod, fall back to -1 */
1554+
if (result != exprTypmod(expr))
1555+
return -1;
1556+
}
1557+
}
1558+
1559+
return result;
1560+
}
1561+
15251562
/*
15261563
* check_generic_type_consistency()
15271564
* Are the actual arguments potentially compatible with a

src/backend/parser/parse_func.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -1750,6 +1750,7 @@ unify_hypothetical_args(ParseState *pstate,
17501750
ListCell *harg = list_nth_cell(fargs, hargpos);
17511751
ListCell *aarg = list_nth_cell(fargs, aargpos);
17521752
Oid commontype;
1753+
int32 commontypmod;
17531754

17541755
/* A mismatch means AggregateCreate didn't check properly ... */
17551756
if (declared_arg_types[hargpos] != declared_arg_types[aargpos])
@@ -1768,6 +1769,9 @@ unify_hypothetical_args(ParseState *pstate,
17681769
list_make2(lfirst(aarg), lfirst(harg)),
17691770
"WITHIN GROUP",
17701771
NULL);
1772+
commontypmod = select_common_typmod(pstate,
1773+
list_make2(lfirst(aarg), lfirst(harg)),
1774+
commontype);
17711775

17721776
/*
17731777
* Perform the coercions. We don't need to worry about NamedArgExprs
@@ -1776,15 +1780,15 @@ unify_hypothetical_args(ParseState *pstate,
17761780
lfirst(harg) = coerce_type(pstate,
17771781
(Node *) lfirst(harg),
17781782
actual_arg_types[hargpos],
1779-
commontype, -1,
1783+
commontype, commontypmod,
17801784
COERCION_IMPLICIT,
17811785
COERCE_IMPLICIT_CAST,
17821786
-1);
17831787
actual_arg_types[hargpos] = commontype;
17841788
lfirst(aarg) = coerce_type(pstate,
17851789
(Node *) lfirst(aarg),
17861790
actual_arg_types[aargpos],
1787-
commontype, -1,
1791+
commontype, commontypmod,
17881792
COERCION_IMPLICIT,
17891793
COERCE_IMPLICIT_CAST,
17901794
-1);

src/include/parser/parse_coerce.h

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
7171
Oid targetTypeId,
7272
const char *context);
7373

74+
extern int32 select_common_typmod(ParseState *pstate, List *exprs, Oid common_type);
75+
7476
extern bool check_generic_type_consistency(const Oid *actual_arg_types,
7577
const Oid *declared_arg_types,
7678
int nargs);

0 commit comments

Comments
 (0)