git.postgresql.org Git - postgresql.git/commitdiff

git projects / postgresql.git / commitdiff
? search:
summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e860e74)
Fix UNION/INTERSECT/EXCEPT so that when two inputs being merged have
2006年8月10日 02:36:29 +0000 (02:36 +0000)
2006年8月10日 02:36:29 +0000 (02:36 +0000)
same data type and same typmod, we show that typmod as the output
typmod, rather than generic -1. This responds to several complaints
over the past few years about UNIONs unexpectedly dropping length or
precision info.


diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 8903d6b42dd61f896408a52f0b30d4bd628cfc19..77ccd64a7da9303ceed67cf27f0dec048df9af77 100644 (file)
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.345 2006年08月02日 01:59:45 joe Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.346 2006年08月10日 02:36:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1793,6 +1793,7 @@ _copySetOperationStmt(SetOperationStmt *from)
COPY_NODE_FIELD(larg);
COPY_NODE_FIELD(rarg);
COPY_NODE_FIELD(colTypes);
+ COPY_NODE_FIELD(colTypmods);
return newnode;
}
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index d49e02b3d8afff85df7a6aa050ce9dff2292a986..4b749e0fc6d27742cdb187233d830ddab620d687 100644 (file)
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.279 2006年08月02日 01:59:45 joe Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.280 2006年08月10日 02:36:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -743,6 +743,7 @@ _equalSetOperationStmt(SetOperationStmt *a, SetOperationStmt *b)
COMPARE_NODE_FIELD(larg);
COMPARE_NODE_FIELD(rarg);
COMPARE_NODE_FIELD(colTypes);
+ COMPARE_NODE_FIELD(colTypmods);
return true;
}
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 34555e1c56781c947f6c6a0f85ca33c301ba2ff7..39ac8e4c621815b859ffd45b8e958456a870b927 100644 (file)
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.280 2006年08月02日 01:59:45 joe Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.281 2006年08月10日 02:36:28 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
@@ -1574,6 +1574,7 @@ _outSetOperationStmt(StringInfo str, SetOperationStmt *node)
WRITE_NODE_FIELD(larg);
WRITE_NODE_FIELD(rarg);
WRITE_NODE_FIELD(colTypes);
+ WRITE_NODE_FIELD(colTypmods);
}
static void
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 7459acb30c006804cf3a8497ad391602ab642944..80fa88e0da5ecbd5c6076cd1daea43f92a085b09 100644 (file)
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.193 2006年08月02日 01:59:45 joe Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.194 2006年08月10日 02:36:28 tgl Exp $
*
* NOTES
* Path and Plan nodes do not have any readfuncs support, because we
@@ -245,6 +245,7 @@ _readSetOperationStmt(void)
READ_NODE_FIELD(larg);
READ_NODE_FIELD(rarg);
READ_NODE_FIELD(colTypes);
+ READ_NODE_FIELD(colTypmods);
READ_DONE();
}
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 1d7e20c1e8b957ed329103dd026e50839a188176..fc618f72d1cc0878fafc8bff66a113c718de9391 100644 (file)
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.150 2006年08月02日 01:59:45 joe Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.151 2006年08月10日 02:36:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -813,6 +813,10 @@ recurse_pushdown_safe(Node *setOp, Query *topquery,
* Compare tlist's datatypes against the list of set-operation result types.
* For any items that are different, mark the appropriate element of
* differentTypes[] to show that this column will have type conversions.
+ *
+ * We don't have to care about typmods here: the only allowed difference
+ * between set-op input and output typmods is input is a specific typmod
+ * and output is -1, and that does not require a coercion.
*/
static void
compare_tlist_datatypes(List *tlist, List *colTypes,
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 856181d090dfbcda4da447972ae0da7750669c70..2fe78473048451951a57293458d7c37028dbb257 100644 (file)
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.39 2006年07月14日 14:52:21 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.40 2006年08月10日 02:36:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -716,6 +716,7 @@ is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
Assert(subquery != NULL);
/* Leaf nodes are OK if they match the toplevel column types */
+ /* We don't have to compare typmods here */
return tlist_same_datatypes(subquery->targetList, colTypes, true);
}
else if (IsA(setOp, SetOperationStmt))
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 3b9e740cadff34fb4d405dcf9953480ebbe795fe..3bf7223199f06a66968cb6cdc52d676fdf3c5581 100644 (file)
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -22,7 +22,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.132 2006年04月30日 18:30:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.133 2006年08月10日 02:36:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -152,6 +152,10 @@ plan_set_operations(PlannerInfo *root, double tuple_fraction,
* flag: if >= 0, add a resjunk output column indicating value of flag
* refnames_tlist: targetlist to take column names from
* *sortClauses: receives list of SortClauses for result plan, if any
+ *
+ * We don't have to care about typmods here: the only allowed difference
+ * between set-op input and output typmods is input is a specific typmod
+ * and output is -1, and that does not require a coercion.
*/
static Plan *
recurse_set_operations(Node *setOp, PlannerInfo *root,
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index c75c496065c2af4af120c6839cb7c4c6b0144814..74ebb3fc24b3723db9c2663d2b83d012a0bc8ea0 100644 (file)
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/tlist.c,v 1.72 2006年03月05日 15:58:32 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/tlist.c,v 1.73 2006年08月10日 02:36:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -174,6 +174,8 @@ get_sortgrouplist_exprs(List *sortClauses, List *targetList)
*
* Resjunk columns are ignored if junkOK is true; otherwise presence of
* a resjunk column will always cause a 'false' result.
+ *
+ * Note: currently no callers care about comparing typmods.
*/
bool
tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 4f00d98b9b696edb430bf24e7fca75429c6e0842..6921e1d77c83842115968180da0a56aecef954b5 100644 (file)
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.343 2006年08月02日 14:14:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.344 2006年08月10日 02:36:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -131,7 +131,8 @@ static void transformFKConstraints(ParseState *pstate,
bool skipValidation,
bool isAddConstraint);
static void applyColumnNames(List *dst, List *src);
-static List *getSetColTypes(ParseState *pstate, Node *node);
+static void getSetColTypes(ParseState *pstate, Node *node,
+ List **colTypes, List **colTypmods);
static void transformLockingClause(Query *qry, LockingClause *lc);
static void transformConstraintAttrs(List *constraintList);
static void transformColumnType(ParseState *pstate, ColumnDef *column);
@@ -2312,7 +2313,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
List *lockingClause;
Node *node;
ListCell *left_tlist,
- *dtlist,
+ *lct,
+ *lcm,
*l;
List *targetvars,
*targetnames,
@@ -2395,9 +2397,10 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
targetnames = NIL;
left_tlist = list_head(leftmostQuery->targetList);
- foreach(dtlist, sostmt->colTypes)
+ forboth(lct, sostmt->colTypes, lcm, sostmt->colTypmods)
{
- Oid colType = lfirst_oid(dtlist);
+ Oid colType = lfirst_oid(lct);
+ int32 colTypmod = lfirst_int(lcm);
TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
char *colName;
TargetEntry *tle;
@@ -2408,7 +2411,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
expr = (Expr *) makeVar(leftmostRTI,
lefttle->resno,
colType,
- -1,
+ colTypmod,
0);
tle = makeTargetEntry(expr,
(AttrNumber) pstate->p_next_resno++,
@@ -2609,8 +2612,12 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
SetOperationStmt *op = makeNode(SetOperationStmt);
List *lcoltypes;
List *rcoltypes;
- ListCell *l;
- ListCell *r;
+ List *lcoltypmods;
+ List *rcoltypmods;
+ ListCell *lct;
+ ListCell *rct;
+ ListCell *lcm;
+ ListCell *rcm;
const char *context;
context = (stmt->op == SETOP_UNION ? "UNION" :
@@ -2630,24 +2637,43 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
* Verify that the two children have the same number of non-junk
* columns, and determine the types of the merged output columns.
*/
- lcoltypes = getSetColTypes(pstate, op->larg);
- rcoltypes = getSetColTypes(pstate, op->rarg);
+ getSetColTypes(pstate, op->larg, &lcoltypes, &lcoltypmods);
+ getSetColTypes(pstate, op->rarg, &rcoltypes, &rcoltypmods);
if (list_length(lcoltypes) != list_length(rcoltypes))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("each %s query must have the same number of columns",
context)));
+ Assert(list_length(lcoltypes) == list_length(lcoltypmods));
+ Assert(list_length(rcoltypes) == list_length(rcoltypmods));
op->colTypes = NIL;
- forboth(l, lcoltypes, r, rcoltypes)
+ op->colTypmods = NIL;
+ /* don't have a "foreach4", so chase two of the lists by hand */
+ lcm = list_head(lcoltypmods);
+ rcm = list_head(rcoltypmods);
+ forboth(lct, lcoltypes, rct, rcoltypes)
{
- Oid lcoltype = lfirst_oid(l);
- Oid rcoltype = lfirst_oid(r);
+ Oid lcoltype = lfirst_oid(lct);
+ Oid rcoltype = lfirst_oid(rct);
+ int32 lcoltypmod = lfirst_int(lcm);
+ int32 rcoltypmod = lfirst_int(rcm);
Oid rescoltype;
+ int32 rescoltypmod;
+ /* select common type, same as CASE et al */
rescoltype = select_common_type(list_make2_oid(lcoltype, rcoltype),
context);
+ /* if same type and same typmod, use typmod; else default */
+ if (lcoltype == rcoltype && lcoltypmod == rcoltypmod)
+ rescoltypmod = lcoltypmod;
+ else
+ rescoltypmod = -1;
op->colTypes = lappend_oid(op->colTypes, rescoltype);
+ op->colTypmods = lappend_int(op->colTypmods, rescoltypmod);
+
+ lcm = lnext(lcm);
+ rcm = lnext(rcm);
}
return (Node *) op;
@@ -2656,17 +2682,19 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
/*
* getSetColTypes
- * Get output column types of an (already transformed) set-op node
+ * Get output column types/typmods of an (already transformed) set-op node
*/
-static List *
-getSetColTypes(ParseState *pstate, Node *node)
+static void
+getSetColTypes(ParseState *pstate, Node *node,
+ List **colTypes, List **colTypmods)
{
+ *colTypes = NIL;
+ *colTypmods = NIL;
if (IsA(node, RangeTblRef))
{
RangeTblRef *rtr = (RangeTblRef *) node;
RangeTblEntry *rte = rt_fetch(rtr->rtindex, pstate->p_rtable);
Query *selectQuery = rte->subquery;
- List *result = NIL;
ListCell *tl;
Assert(selectQuery != NULL);
@@ -2677,9 +2705,11 @@ getSetColTypes(ParseState *pstate, Node *node)
if (tle->resjunk)
continue;
- result = lappend_oid(result, exprType((Node *) tle->expr));
+ *colTypes = lappend_oid(*colTypes,
+ exprType((Node *) tle->expr));
+ *colTypmods = lappend_int(*colTypmods,
+ exprTypmod((Node *) tle->expr));
}
- return result;
}
else if (IsA(node, SetOperationStmt))
{
@@ -2687,13 +2717,11 @@ getSetColTypes(ParseState *pstate, Node *node)
/* Result already computed during transformation of node */
Assert(op->colTypes != NIL);
- return op->colTypes;
+ *colTypes = op->colTypes;
+ *colTypmods = op->colTypmods;
}
else
- {
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
- return NIL; /* keep compiler quiet */
- }
}
/* Attach column names from a ColumnDef list to a TargetEntry list */
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index dbf03959054064e978af6b0863e16bba42310278..b97c3d07ec18621db56cd7f623bcbdd876e101e7 100644 (file)
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.347 2006年08月06日 03:53:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.348 2006年08月10日 02:36:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200608051
+#define CATALOG_VERSION_NO 200608091
#endif
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index d0fa16ff51c63dc104c5cef42caac3a2d5d58c48..e2567ff8e441e75e4271fc26513f0cb6da52bf18 100644 (file)
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.320 2006年08月02日 01:59:47 joe Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.321 2006年08月10日 02:36:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -769,7 +769,8 @@ typedef struct SetOperationStmt
/* Eventually add fields for CORRESPONDING spec here */
/* Fields derived during parse analysis: */
- List *colTypes; /* list of OIDs of output column types */
+ List *colTypes; /* OID list of output column type OIDs */
+ List *colTypmods; /* integer list of output column typmods */
} SetOperationStmt;
This is the main PostgreSQL git repository.
RSS Atom

AltStyle によって変換されたページ (->オリジナル) /