diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result
index f18d1c9b5838b98c9ad87e1b3b1486ef7e84683b..064304b27aa09915d88aad83017d491d46b6c80c 100644
--- a/mysql-test/r/bigint.result
+++ b/mysql-test/r/bigint.result
@@ -362,3 +362,29 @@ cast(-19999999999999999999 as signed)
 -9223372036854775808
 Warnings:
 Error	1292	Truncated incorrect DECIMAL value: ''
+select -9223372036854775808;
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max length	Is_null	Flags	Decimals	Charsetnr
+def					-9223372036854775808	8	20	20	N	32897	0	63
+-9223372036854775808
+-9223372036854775808
+select -(9223372036854775808);
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max length	Is_null	Flags	Decimals	Charsetnr
+def					-(9223372036854775808)	8	20	20	N	32897	0	63
+-(9223372036854775808)
+-9223372036854775808
+select -((9223372036854775808));
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max length	Is_null	Flags	Decimals	Charsetnr
+def					-((9223372036854775808))	8	20	20	N	32897	0	63
+-((9223372036854775808))
+-9223372036854775808
+select -(-(9223372036854775808));
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max length	Is_null	Flags	Decimals	Charsetnr
+def					-(-(9223372036854775808))	246	21	19	N	129	0	63
+-(-(9223372036854775808))
+9223372036854775808
+select --9223372036854775808, ---9223372036854775808, ----9223372036854775808;
+--9223372036854775808	---9223372036854775808	----9223372036854775808
+9223372036854775808	-9223372036854775808	9223372036854775808
+select -(-9223372036854775808), -(-(-9223372036854775808));
+-(-9223372036854775808)	-(-(-9223372036854775808))
+9223372036854775808	-9223372036854775808
diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test
index 9a5fb11229d32b9b06ad561e4b8784422b77b362..1f0f7763e878c79f4e3fd6778983411f3d2d71f2 100644
--- a/mysql-test/t/bigint.test
+++ b/mysql-test/t/bigint.test
@@ -294,3 +294,16 @@ drop table t1;
 
 select cast(19999999999999999999 as signed);
 select cast(-19999999999999999999 as signed);
+
+#
+# Bug #28625: -9223372036854775808 doesn't fit in BIGINT.
+#
+
+--enable_metadata
+select -9223372036854775808;
+select -(9223372036854775808);
+select -((9223372036854775808));
+select -(-(9223372036854775808));
+--disable_metadata
+select --9223372036854775808, ---9223372036854775808, ----9223372036854775808;
+select -(-9223372036854775808), -(-(-9223372036854775808));
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 17a2c584e9db25089dfc3cdbcda1aac1e4d34f37..b256ce4624abe31a2552187dd23c3df4549cd173 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1523,16 +1523,20 @@ void Item_func_neg::fix_length_and_dec()
     Use val() to get value as arg_type doesn't mean that item is
     Item_int or Item_real due to existence of Item_param.
   */
-  if (hybrid_type == INT_RESULT &&
-      args[0]->type() == INT_ITEM &&
-      ((ulonglong) args[0]->val_int() >= (ulonglong) LONGLONG_MIN))
+  if (hybrid_type == INT_RESULT && args[0]->const_item())
   {
-    /*
-      Ensure that result is converted to DECIMAL, as longlong can't hold
-      the negated number
-    */
-    hybrid_type= DECIMAL_RESULT;
-    DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
+    longlong val= args[0]->val_int();
+    if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
+        ((ulonglong) val != (ulonglong) LONGLONG_MIN ||
+          args[0]->type() != INT_ITEM))        
+    {
+      /*
+        Ensure that result is converted to DECIMAL, as longlong can't hold
+        the negated number
+      */
+      hybrid_type= DECIMAL_RESULT;
+      DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
+    }
   }
   unsigned_flag= 0;
   DBUG_VOID_RETURN;