tinyint(1) is assumed to be boolean

Issue #1210 resolved
Former user created an issue

SQLAlchemy assumes that {{{tinyint(1)}}} on MySQL tables is a boolean. This is wrong however, since the 1 is just for displaying purposes (see MySQL docs), you can assign any value from -128–127 to an {{{tinyint(1)}}} column, there is no difference to {{{tinyint(4)}}}.

Fixing this would cause integers to be returned for {{{BOOLEAN}}} columns, but this is much less painful than returning True instead of 2. In Python, {{{1 == True}}}, so this won't be a problem (and usually you use the return value in a boolean context anyway, so it is even less a problem ;-) )

test case

from sqlalchemy import create_engine, Table, Column, Integer, MetaData
engine = create_engine('mysql://localhost/test')
metadata = MetaData()
conn = engine.connect()
conn.execute('CREATE TABLE tinyint_demo (number TINYINT(1) NOT NULL);')
conn.execute('INSERT INTO tinyint_demo VALUES (0);')
conn.execute('INSERT INTO tinyint_demo VALUES (1);')
conn.execute('INSERT INTO tinyint_demo VALUES (2);')
metadata.bind = engine
table = Table('tinyint_demo', metadata, autoload=True)
conn.execute(table.select()).fetchall()

Comments (1)

  1. jek

    TINYINT(1) is the MySQL idiom for booelans and is how a CREATE TABLE (toggle BOOLEAN) reflects. I haven't seen any rational from the mysql folks on why they chose this, but I'd guess that it's because specifying a TINYINT(1) column is meaningless- it translates to 'Store a 1 byte number, and always display at least 1 digit if non-NULL.'

    If a reflected schema has TINYINT(1) that are not boolean, overriding them with plain TINYINT columns will allow integers to pass through. Otherwise they'll use the standard mysql behavior: 0 is False, non-zero is True.

  2. Log in to comment