diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result
index 8b59fa371cce0c75edde5be543af206b73ccb691..a9024156c6e27fc786b1135d7a1dcbffdc225209 100644
--- a/mysql-test/r/sp-vars.result
+++ b/mysql-test/r/sp-vars.result
@@ -431,17 +431,17 @@ SELECT HEX(v10);
 END|
 CALL p1();
 HEX(v1)
-01
+1
 HEX(v2)
-00
+0
 HEX(v3)
-05
+5
 HEX(v4)
 5555555555555555
 HEX(v5)
-07
+7
 HEX(v6)
-0000000000000005
+5
 HEX(v7)
 80
 HEX(v8)
@@ -748,12 +748,60 @@ HEX(b)	b = 0	b = FALSE	b IS FALSE	b = 1	b = TRUE	b IS TRUE
 1	0	0	0	1	1	1
 call p2();
 HEX(vb)	vb = 0	vb = FALSE	vb IS FALSE	vb = 1	vb = TRUE	vb IS TRUE
-00	1	1	1	0	0	0
+0	1	1	1	0	0	0
 HEX(vb)	vb = 0	vb = FALSE	vb IS FALSE	vb = 1	vb = TRUE	vb IS TRUE
-01	0	0	1	1	1	0
+1	0	0	0	1	1	1
 DROP TABLE t1;
 DROP PROCEDURE p1;
 DROP PROCEDURE p2;
+DROP TABLE IF EXISTS table_12976_a;
+DROP TABLE IF EXISTS table_12976_b;
+DROP PROCEDURE IF EXISTS proc_12976_a;
+DROP PROCEDURE IF EXISTS proc_12976_b;
+CREATE TABLE table_12976_a (val bit(1));
+CREATE TABLE table_12976_b(
+appname varchar(15),
+emailperm bit not null default 1,
+phoneperm bit not null default 0);
+insert into table_12976_b values ('A', b'1', b'1'), ('B', b'0', b'0');
+CREATE PROCEDURE proc_12976_a()
+BEGIN
+declare localvar bit(1);
+SELECT val INTO localvar FROM table_12976_a;
+SELECT coalesce(localvar, 1)+1, coalesce(val, 1)+1 FROM table_12976_a;
+END||
+CREATE PROCEDURE proc_12976_b(
+name varchar(15),
+out ep bit,
+out msg varchar(10))
+BEGIN
+SELECT emailperm into ep FROM table_12976_b where (appname = name);
+IF ep is true THEN
+SET msg = 'True';
+ELSE
+SET msg = 'False';
+END IF;
+END||
+INSERT table_12976_a VALUES (0);
+call proc_12976_a();
+coalesce(localvar, 1)+1	coalesce(val, 1)+1
+1	1
+UPDATE table_12976_a set val=1;
+call proc_12976_a();
+coalesce(localvar, 1)+1	coalesce(val, 1)+1
+2	2
+call proc_12976_b('A', @ep, @msg);
+select @ep, @msg;
+@ep	@msg
+1	True
+call proc_12976_b('B', @ep, @msg);
+select @ep, @msg;
+@ep	@msg
+0	False
+DROP TABLE table_12976_a;
+DROP TABLE table_12976_b;
+DROP PROCEDURE proc_12976_a;
+DROP PROCEDURE proc_12976_b;
 
 ---------------------------------------------------------------
 BUG#9572
diff --git a/mysql-test/t/sp-vars.test b/mysql-test/t/sp-vars.test
index 7cf92dc5d0de95b138592e81c64892f4f49bf718..0014dc1f6afebacf5e98ca47d68576abbd0b5b73 100644
--- a/mysql-test/t/sp-vars.test
+++ b/mysql-test/t/sp-vars.test
@@ -500,8 +500,6 @@ DROP PROCEDURE p1;
 #
 # Test case for BUG#12976: Boolean values reversed in stored procedures?
 #
-# TODO: test case failed.
-#
 ###########################################################################
 
 --echo
@@ -566,13 +564,8 @@ BEGIN
 END|
 delimiter ;|
 
-# The expected and correct result.
-
 call p1();
 
-# The wrong result. Note that only hex(vb) works, but is printed with two
-# digits for some reason in this case.
-
 call p2();
 
 #
@@ -583,6 +576,64 @@ DROP TABLE t1;
 DROP PROCEDURE p1;
 DROP PROCEDURE p2;
 
+# Additional tests for Bug#12976
+
+--disable_warnings
+DROP TABLE IF EXISTS table_12976_a;
+DROP TABLE IF EXISTS table_12976_b;
+DROP PROCEDURE IF EXISTS proc_12976_a;
+DROP PROCEDURE IF EXISTS proc_12976_b;
+--enable_warnings
+
+CREATE TABLE table_12976_a (val bit(1));
+
+CREATE TABLE table_12976_b(
+  appname varchar(15),
+  emailperm bit not null default 1,
+  phoneperm bit not null default 0);
+
+insert into table_12976_b values ('A', b'1', b'1'), ('B', b'0', b'0');
+
+delimiter ||;
+CREATE PROCEDURE proc_12976_a()
+BEGIN
+  declare localvar bit(1);
+  SELECT val INTO localvar FROM table_12976_a;
+  SELECT coalesce(localvar, 1)+1, coalesce(val, 1)+1 FROM table_12976_a;
+END||
+
+CREATE PROCEDURE proc_12976_b(
+  name varchar(15),
+  out ep bit,
+  out msg varchar(10))
+BEGIN
+  SELECT emailperm into ep FROM table_12976_b where (appname = name);
+  IF ep is true THEN
+    SET msg = 'True';
+  ELSE
+    SET msg = 'False';
+  END IF;
+END||
+
+delimiter ;||
+
+INSERT table_12976_a VALUES (0);
+call proc_12976_a();
+UPDATE table_12976_a set val=1;
+call proc_12976_a();
+
+call proc_12976_b('A', @ep, @msg);
+select @ep, @msg;
+
+call proc_12976_b('B', @ep, @msg);
+select @ep, @msg;
+
+DROP TABLE table_12976_a;
+DROP TABLE table_12976_b;
+DROP PROCEDURE proc_12976_a;
+DROP PROCEDURE proc_12976_b;
+
+
 ###########################################################################
 #
 # Test case for BUG#9572: Stored procedures: variable type declarations
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 7c110185a95f2a8f585e474d06250d765c4a3575..ed1d55a900f63021a4a33382fdfba35ed46e684e 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -36,6 +36,7 @@ Item_result
 sp_map_result_type(enum enum_field_types type)
 {
   switch (type) {
+  case MYSQL_TYPE_BIT:
   case MYSQL_TYPE_TINY:
   case MYSQL_TYPE_SHORT:
   case MYSQL_TYPE_LONG:
@@ -58,6 +59,7 @@ Item::Type
 sp_map_item_type(enum enum_field_types type)
 {
   switch (type) {
+  case MYSQL_TYPE_BIT:
   case MYSQL_TYPE_TINY:
   case MYSQL_TYPE_SHORT:
   case MYSQL_TYPE_LONG: