diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 74b0b99acd0622146c3551658bfa448f3dd0d4f3..0fbca231756f4845d4242ba4b4c24e05e8025c7f 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -14,7 +14,7 @@
  * Copyright (c) 1998-2009, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.116 2009/01/01 17:23:49 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.117 2009/04/08 22:08:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -242,7 +242,8 @@ static void alloc_var(NumericVar *var, int ndigits);
 static void free_var(NumericVar *var);
 static void zero_var(NumericVar *var);
 
-static void set_var_from_str(const char *str, NumericVar *dest);
+static const char *set_var_from_str(const char *str, const char *cp,
+									NumericVar *dest);
 static void set_var_from_num(Numeric value, NumericVar *dest);
 static void set_var_from_var(NumericVar *value, NumericVar *dest);
 static char *get_str_from_var(NumericVar *var, int dscale);
@@ -321,26 +322,69 @@ numeric_in(PG_FUNCTION_ARGS)
 	Oid			typelem = PG_GETARG_OID(1);
 #endif
 	int32		typmod = PG_GETARG_INT32(2);
-	NumericVar	value;
 	Numeric		res;
+	const char *cp;
+
+	/* Skip leading spaces */
+	cp = str;
+	while (*cp)
+	{
+		if (!isspace((unsigned char) *cp))
+			break;
+		cp++;
+	}
 
 	/*
 	 * Check for NaN
 	 */
-	if (pg_strcasecmp(str, "NaN") == 0)
-		PG_RETURN_NUMERIC(make_result(&const_nan));
+	if (pg_strncasecmp(cp, "NaN", 3) == 0)
+	{
+		res = make_result(&const_nan);
 
-	/*
-	 * Use set_var_from_str() to parse the input string and return it in the
-	 * packed DB storage format
-	 */
-	init_var(&value);
-	set_var_from_str(str, &value);
+		/* Should be nothing left but spaces */
+		cp += 3;
+		while (*cp)
+		{
+			if (!isspace((unsigned char) *cp))
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+					 errmsg("invalid input syntax for type numeric: \"%s\"",
+							str)));
+			cp++;
+		}
+	}
+	else
+	{
+		/*
+		 * Use set_var_from_str() to parse a normal numeric value
+		 */
+		NumericVar	value;
 
-	apply_typmod(&value, typmod);
+		init_var(&value);
 
-	res = make_result(&value);
-	free_var(&value);
+		cp = set_var_from_str(str, cp, &value);
+
+		/*
+		 * We duplicate a few lines of code here because we would like to
+		 * throw any trailing-junk syntax error before any semantic error
+		 * resulting from apply_typmod.  We can't easily fold the two
+		 * cases together because we mustn't apply apply_typmod to a NaN.
+		 */
+		while (*cp)
+		{
+			if (!isspace((unsigned char) *cp))
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+					 errmsg("invalid input syntax for type numeric: \"%s\"",
+							str)));
+			cp++;
+		}
+
+		apply_typmod(&value, typmod);
+
+		res = make_result(&value);
+		free_var(&value);
+	}
 
 	PG_RETURN_NUMERIC(res);
 }
@@ -2121,7 +2165,9 @@ float8_numeric(PG_FUNCTION_ARGS)
 
 	init_var(&result);
 
-	set_var_from_str(buf, &result);
+	/* Assume we need not worry about leading/trailing spaces */
+	(void) set_var_from_str(buf, buf, &result);
+
 	res = make_result(&result);
 
 	free_var(&result);
@@ -2181,7 +2227,9 @@ float4_numeric(PG_FUNCTION_ARGS)
 
 	init_var(&result);
 
-	set_var_from_str(buf, &result);
+	/* Assume we need not worry about leading/trailing spaces */
+	(void) set_var_from_str(buf, buf, &result);
+
 	res = make_result(&result);
 
 	free_var(&result);
@@ -2972,11 +3020,17 @@ zero_var(NumericVar *var)
  * set_var_from_str()
  *
  *	Parse a string and put the number into a variable
+ *
+ * This function does not handle leading or trailing spaces, and it doesn't
+ * accept "NaN" either.  It returns the end+1 position so that caller can
+ * check for trailing spaces/garbage if deemed necessary.
+ *
+ * cp is the place to actually start parsing; str is what to use in error
+ * reports.  (Typically cp would be the same except advanced over spaces.)
  */
-static void
-set_var_from_str(const char *str, NumericVar *dest)
+static const char *
+set_var_from_str(const char *str, const char *cp, NumericVar *dest)
 {
-	const char *cp = str;
 	bool		have_dp = FALSE;
 	int			i;
 	unsigned char *decdigits;
@@ -2993,15 +3047,6 @@ set_var_from_str(const char *str, NumericVar *dest)
 	 * We first parse the string to extract decimal digits and determine the
 	 * correct decimal weight.	Then convert to NBASE representation.
 	 */
-
-	/* skip leading spaces */
-	while (*cp)
-	{
-		if (!isspace((unsigned char) *cp))
-			break;
-		cp++;
-	}
-
 	switch (*cp)
 	{
 		case '+':
@@ -3086,17 +3131,6 @@ set_var_from_str(const char *str, NumericVar *dest)
 			dscale = 0;
 	}
 
-	/* Should be nothing left but spaces */
-	while (*cp)
-	{
-		if (!isspace((unsigned char) *cp))
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-					 errmsg("invalid input syntax for type numeric: \"%s\"",
-							str)));
-		cp++;
-	}
-
 	/*
 	 * Okay, convert pure-decimal representation to base NBASE.  First we need
 	 * to determine the converted weight and ndigits.  offset is the number of
@@ -3137,6 +3171,9 @@ set_var_from_str(const char *str, NumericVar *dest)
 
 	/* Strip any leading/trailing zeroes, and normalize weight if zero */
 	strip_var(dest);
+
+	/* Return end+1 position for caller */
+	return cp;
 }
 
 
diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out
index c2fe7070b50411ac667d5dabef558145e2654fbc..a3b631aabe0d642b0ac060f2261be861adc15395 100644
--- a/src/test/regress/expected/numeric.out
+++ b/src/test/regress/expected/numeric.out
@@ -1230,13 +1230,7 @@ INSERT INTO num_input_test(n1) VALUES ('  -93853');
 INSERT INTO num_input_test(n1) VALUES ('555.50');
 INSERT INTO num_input_test(n1) VALUES ('-555.50');
 INSERT INTO num_input_test(n1) VALUES ('NaN ');
-ERROR:  invalid input syntax for type numeric: "NaN "
-LINE 1: INSERT INTO num_input_test(n1) VALUES ('NaN ');
-                                               ^
 INSERT INTO num_input_test(n1) VALUES ('        nan');
-ERROR:  invalid input syntax for type numeric: "        nan"
-LINE 1: INSERT INTO num_input_test(n1) VALUES ('        nan');
-                                               ^
 -- bad inputs
 INSERT INTO num_input_test(n1) VALUES ('     ');
 ERROR:  invalid input syntax for type numeric: "     "
@@ -1278,7 +1272,9 @@ SELECT * FROM num_input_test;
   -93853
   555.50
  -555.50
-(5 rows)
+     NaN
+     NaN
+(7 rows)
 
 --
 -- Test some corner cases for division