Skip to content

A bit(1) field from a subquery returns 48 for false and 49 for true #708

@lauxjpn

Description

@lauxjpn

While fixing the last Pomelo.MySql tests, I came across this strange bug.

The following schema and query will run fine in MySQL Workbench for MySQL 8.0.17:

CREATE TABLE `Weapons` (
  `IsAutomatic` bit(1) NOT NULL
) ENGINE=InnoDB;

insert into `Weapons` (`IsAutomatic`) values (0);
insert into `Weapons` (`IsAutomatic`) values (1);

CREATE TABLE `Gears` (
  `Nickname` varchar(255) NOT NULL
) ENGINE=InnoDB;

insert into `Gears` (`Nickname`) values ('Baird');
insert into `Gears` (`Nickname`) values ('Dom');

SELECT (
    SELECT `w`.`IsAutomatic`
    FROM `Weapons` AS `w`
    LIMIT 1
) as `MyColumn`
FROM `Gears` AS `g`;

The query returns the following result set, which is correct:

MyColumn
0
0

Using the same schema to execute the same query with MySqlConnector, the following result set is returned, which is incorrect:

MyColumn
48
48

I used the following console project for the MySqlConnector test:

using System;
using System.Diagnostics;
using MySql.Data.MySqlClient;

namespace CustomConsoleTest
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            using var connection = new MySqlConnection(
                "server=127.0.0.1;user id=root;password=;port=3306;database=SubqueryBug");
            connection.Open();

            using var command = connection.CreateCommand();
            command.CommandText = @"
SELECT (
    SELECT `w`.`IsAutomatic`
    FROM `Weapons` AS `w`
    LIMIT 1
) as `MyColumn`
FROM `Gears` AS `g`";

            using var reader = command.ExecuteReader();
            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    // The bit(1) field `Weapons`.`IsAutomatic` somehow
                    // returns 48 (as false) or 49 (as true).
                    var value = reader.GetValue(0);

                    Console.WriteLine($"Value: {value}");
                    Debug.Assert(value is bool ||
                                 Convert.ToUInt64(value) == 0 ||
                                 Convert.ToUInt64(value) == 1);
                }
            }
        }
    }
}

It appears, that if a bit(1) column is returned from a subquery within a select statement, the returned value is off by 48. So 48 should actually be 0 and 49 should actually be 1.
Maybe some bit shifting bug?

Explicitly casting the value as another type like decimal, returns the correct result set in MySqlConnector:

SELECT (
	SELECT cast(`w`.`IsAutomatic` as decimal)
	FROM `Weapons` AS `w`
	LIMIT 1
)
FROM `Gears` AS `g`

Removing the outer query entirely and just executing the sub query, will also return a correct result set (in this case just one 0):

SELECT `w`.`IsAutomatic`
FROM `Weapons` AS `w`
LIMIT 1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions