summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2007-09-06 17:31:58 +0000
committerTom Lane2007-09-06 17:31:58 +0000
commit983a9105e7ac09f5a4fb8d0b4e85ef81626c9147 (patch)
treed71dfc4c9297e31732d305a890c25903a6470baa
parent90fbb102c26ecf2990758c199bb637e9e1252b1c (diff)
Make eval_const_expressions() preserve typmod when simplifying something like
null::char(3) to a simple Const node. (It already worked for non-null values, but not when we skipped evaluation of a strict coercion function.) This prevents loss of typmod knowledge in situations such as exhibited in bug #3598. Unfortunately there seems no good way to fix that bug in 8.1 and 8.2, because they simply don't carry a typmod for a plain Const node. In passing I made all the other callers of makeNullConst supply "real" typmod values too, though I think it probably doesn't matter anywhere else.
-rw-r--r--src/backend/commands/tablecmds.c9
-rw-r--r--src/backend/executor/execQual.c2
-rw-r--r--src/backend/nodes/makefuncs.c9
-rw-r--r--src/backend/optimizer/util/clauses.c4
-rw-r--r--src/backend/parser/parse_coerce.c2
-rw-r--r--src/backend/parser/parse_relation.c2
-rw-r--r--src/backend/parser/parse_target.c2
-rw-r--r--src/backend/rewrite/rewriteHandler.c2
-rw-r--r--src/backend/rewrite/rewriteManip.c3
-rw-r--r--src/include/nodes/makefuncs.h2
10 files changed, 21 insertions, 16 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 77e4b5e1cd..ede192298f 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -3179,12 +3179,15 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
if (!defval && GetDomainConstraints(typeOid) != NIL)
{
- Oid basetype = getBaseType(typeOid);
+ Oid baseTypeId;
+ int32 baseTypeMod;
- defval = (Expr *) makeNullConst(basetype);
+ baseTypeMod = typmod;
+ baseTypeId = getBaseTypeAndTypmod(typeOid, &baseTypeMod);
+ defval = (Expr *) makeNullConst(baseTypeId, baseTypeMod);
defval = (Expr *) coerce_to_target_type(NULL,
(Node *) defval,
- basetype,
+ baseTypeId,
typeOid,
typmod,
COERCION_ASSIGNMENT,
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 7acc7b255c..a6a970e759 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -4159,7 +4159,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
* don't really care what type of NULL it is, so
* always make an int4 NULL.
*/
- e = (Expr *) makeNullConst(INT4OID);
+ e = (Expr *) makeNullConst(INT4OID, -1);
}
estate = ExecInitExpr(e, parent);
outlist = lappend(outlist, estate);
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 6aa17413a4..d83b5b95a5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -174,19 +174,20 @@ makeConst(Oid consttype,
/*
* makeNullConst -
- * creates a Const node representing a NULL of the specified type
+ * creates a Const node representing a NULL of the specified type/typmod
*
- * Note: for all current uses, OK to set typmod of the Const to -1.
+ * This is a convenience routine that just saves a lookup of the type's
+ * storage properties.
*/
Const *
-makeNullConst(Oid consttype)
+makeNullConst(Oid consttype, int32 consttypmod)
{
int16 typLen;
bool typByVal;
get_typlenbyval(consttype, &typLen, &typByVal);
return makeConst(consttype,
- -1,
+ consttypmod,
(int) typLen,
(Datum) 0,
true,
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index a7a2621ee1..afef1cfd47 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -2265,7 +2265,7 @@ eval_const_expressions_mutator(Node *node,
/* If all the arguments were constant null, the result is just null */
if (newargs == NIL)
- return (Node *) makeNullConst(coalesceexpr->coalescetype);
+ return (Node *) makeNullConst(coalesceexpr->coalescetype, -1);
newcoalesce = makeNode(CoalesceExpr);
newcoalesce->coalescetype = coalesceexpr->coalescetype;
@@ -2833,7 +2833,7 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod, List *args,
* function is not otherwise immutable.
*/
if (funcform->proisstrict && has_null_input)
- return (Expr *) makeNullConst(result_type);
+ return (Expr *) makeNullConst(result_type, result_typmod);
/*
* Otherwise, can simplify only if all inputs are constants. (For a
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 7950d034bc..1459b98dbc 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -816,7 +816,7 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
* can't use atttypid here, but it doesn't really matter what type
* the Const claims to be.
*/
- newargs = lappend(newargs, makeNullConst(INT4OID));
+ newargs = lappend(newargs, makeNullConst(INT4OID, -1));
continue;
}
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index dd9499e417..f57e1a4348 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -1448,7 +1448,7 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref,
* can't use atttypid here, but it doesn't really matter
* what type the Const claims to be.
*/
- *colvars = lappend(*colvars, makeNullConst(INT4OID));
+ *colvars = lappend(*colvars, makeNullConst(INT4OID, -1));
}
}
continue;
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index ef9bf189b5..e0c297e68e 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -393,7 +393,7 @@ transformAssignedExpr(ParseState *pstate,
* is not really a source value to work with. Insert a NULL
* constant as the source value.
*/
- colVar = (Node *) makeNullConst(attrtype);
+ colVar = (Node *) makeNullConst(attrtype, attrtypmod);
}
else
{
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index e358d380d2..d83f21f256 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -193,7 +193,7 @@ AcquireRewriteLocks(Query *parsetree)
* now-dropped type OID, but it doesn't really
* matter what type the Const claims to be.
*/
- aliasvar = (Var *) makeNullConst(INT4OID);
+ aliasvar = (Var *) makeNullConst(INT4OID, -1);
}
}
newaliasvars = lappend(newaliasvars, aliasvar);
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index f30e7796c9..fc8be972f7 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -896,7 +896,8 @@ resolve_one_var(Var *var, ResolveNew_context *context)
{
/* Otherwise replace unmatched var with a null */
/* need coerce_to_domain in case of NOT NULL domain constraint */
- return coerce_to_domain((Node *) makeNullConst(var->vartype),
+ return coerce_to_domain((Node *) makeNullConst(var->vartype,
+ var->vartypmod),
InvalidOid, -1,
var->vartype,
COERCE_IMPLICIT_CAST,
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index d8aa5f4fc3..6ae9e1b244 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -45,7 +45,7 @@ extern Const *makeConst(Oid consttype,
bool constisnull,
bool constbyval);
-extern Const *makeNullConst(Oid consttype);
+extern Const *makeNullConst(Oid consttype, int32 consttypmod);
extern Node *makeBoolConst(bool value, bool isnull);