aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_expr.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>1999-12-24 06:43:34 +0000
committerTom Lane <tgl@sss.pgh.pa.us>1999-12-24 06:43:34 +0000
commit350cb386af0d5caf5ae32781e80b8622fb5e4fe1 (patch)
tree9bb76439a628b4db461dc4e1fb8f95753e06c009 /src/backend/parser/parse_expr.c
parentbd5ea42a8d2f6cf484f9b10d8c13894fe88ee7e8 (diff)
downloadpostgresql-350cb386af0d5caf5ae32781e80b8622fb5e4fe1.tar.gz
postgresql-350cb386af0d5caf5ae32781e80b8622fb5e4fe1.zip
Clean up handling of explicit NULL constants. Cases like
SELECT null::text; SELECT int4fac(null); work as expected now. In some cases a NULL must be surrounded by parentheses: SELECT 2 + null; fails SELECT 2 + (null); OK This is a grammatical ambiguity that seems difficult to avoid. Other than that, NULLs seem to behave about like you'd expect. The internal implementation is that NULL constants are typed as UNKNOWN (like untyped string constants) until the parser can deduce the right type.
Diffstat (limited to 'src/backend/parser/parse_expr.c')
-rw-r--r--src/backend/parser/parse_expr.c50
1 files changed, 27 insertions, 23 deletions
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 0b738a87307..dab7161c042 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.62 1999/12/17 01:25:25 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.63 1999/12/24 06:43:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -353,7 +353,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
n->val.type = T_Null;
c->defresult = (Node *) n;
}
- c->defresult = transformExpr(pstate, (Node *) c->defresult, precedence);
+ c->defresult = transformExpr(pstate, c->defresult, precedence);
/* now check types across result clauses... */
c->casetype = exprType(c->defresult);
@@ -369,32 +369,30 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
if (wtype && (wtype != UNKNOWNOID)
&& (wtype != ptype))
{
- /* so far, only nulls so take anything... */
- if (!ptype)
+ if (!ptype || ptype == UNKNOWNOID)
{
+ /* so far, only nulls so take anything... */
ptype = wtype;
pcategory = TypeCategory(ptype);
}
-
- /*
- * both types in different categories? then not
- * much hope...
- */
else if ((TypeCategory(wtype) != pcategory)
|| ((TypeCategory(wtype) == USER_TYPE)
&& (TypeCategory(c->casetype) == USER_TYPE)))
{
+ /*
+ * both types in different categories?
+ * then not much hope...
+ */
elog(ERROR, "CASE/WHEN types '%s' and '%s' not matched",
typeidTypeName(c->casetype), typeidTypeName(wtype));
}
-
- /*
- * new one is preferred and can convert? then take
- * it...
- */
else if (IsPreferredType(pcategory, wtype)
&& can_coerce_type(1, &ptype, &wtype))
{
+ /*
+ * new one is preferred and can convert?
+ * then take it...
+ */
ptype = wtype;
pcategory = TypeCategory(ptype);
}
@@ -404,9 +402,8 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
/* Convert default result clause, if necessary */
if (c->casetype != ptype)
{
- if (!c->casetype)
+ if (!c->casetype || c->casetype == UNKNOWNOID)
{
-
/*
* default clause is NULL, so assign preferred
* type from WHEN clauses...
@@ -694,11 +691,12 @@ exprTypmod(Node *expr)
static Node *
parser_typecast(Value *expr, TypeName *typename, int32 atttypmod)
{
- Const *adt;
- Datum lcp;
+ Const *con;
Type tp;
+ Datum datum;
char *const_string = NULL;
bool string_palloced = false;
+ bool isNull = false;
switch (nodeTag(expr))
{
@@ -713,6 +711,9 @@ parser_typecast(Value *expr, TypeName *typename, int32 atttypmod)
string_palloced = true;
const_string = float8out(&expr->val.dval);
break;
+ case T_Null:
+ isNull = true;
+ break;
default:
elog(ERROR,
"parser_typecast: cannot cast this expression to type '%s'",
@@ -729,12 +730,15 @@ parser_typecast(Value *expr, TypeName *typename, int32 atttypmod)
else
tp = (Type) typenameType(typename->name);
- lcp = stringTypeDatum(tp, const_string, atttypmod);
+ if (isNull)
+ datum = (Datum) NULL;
+ else
+ datum = stringTypeDatum(tp, const_string, atttypmod);
- adt = makeConst(typeTypeId(tp),
+ con = makeConst(typeTypeId(tp),
typeLen(tp),
- (Datum) lcp,
- false,
+ datum,
+ isNull,
typeByVal(tp),
false, /* not a set */
true /* is cast */ );
@@ -742,5 +746,5 @@ parser_typecast(Value *expr, TypeName *typename, int32 atttypmod)
if (string_palloced)
pfree(const_string);
- return (Node *) adt;
+ return (Node *) con;
}