From: Mike Bayer Date: Wed, 16 Mar 2011 15:01:20 +0000 (-0400) Subject: - Fixed the BIT type to allow a "length" parameter, "varying" X-Git-Tag: rel_0_7b3~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f75ea6945cf2f0b727558e2f5c247a94cf2668bf;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - Fixed the BIT type to allow a "length" parameter, "varying" parameter. Reflection also fixed. [ticket:2073] --- diff --git a/CHANGES b/CHANGES index f8383fdaf9..f2a6c79781 100644 --- a/CHANGES +++ b/CHANGES @@ -482,6 +482,9 @@ CHANGES - Added RESERVED_WORDS for postgresql dialect. [ticket:2092] + - Fixed the BIT type to allow a "length" parameter, "varying" + parameter. Reflection also fixed. [ticket:2073] + - informix - Added RESERVED_WORDS informix dialect. [ticket:2092] diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 0848bb0dc7..8bceeef657 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -178,8 +178,14 @@ PGInterval = INTERVAL class BIT(sqltypes.TypeEngine): __visit_name__ = 'BIT' - def __init__(self, length=1): - self.length= length + def __init__(self, length=None, varying=False): + if not varying: + # BIT without VARYING defaults to length 1 + self.length = length or 1 + else: + # but BIT VARYING can be unlimited-length, so no default + self.length = length + self.varying = varying PGBit = BIT @@ -404,7 +410,8 @@ ischema_names = { 'inet': INET, 'cidr': CIDR, 'uuid': UUID, - 'bit':BIT, + 'bit': BIT, + 'bit varying': BIT, 'macaddr': MACADDR, 'double precision' : DOUBLE_PRECISION, 'timestamp' : TIMESTAMP, @@ -648,7 +655,13 @@ class PGTypeCompiler(compiler.GenericTypeCompiler): return "INTERVAL" def visit_BIT(self, type_): - return "BIT(%d)" % type_.length + if type_.varying: + compiled = "BIT VARYING" + if type_.length is not None: + compiled += "(%d)" % type_.length + else: + compiled = "BIT(%d)" % type_.length + return compiled def visit_UUID(self, type_): return "UUID" @@ -1124,6 +1137,7 @@ class PGDialect(default.DefaultDialect): if charlen: charlen = charlen.group(1) kwargs = {} + args = None if attype == 'numeric': if charlen: @@ -1147,6 +1161,12 @@ class PGDialect(default.DefaultDialect): if charlen: kwargs['precision'] = int(charlen) args = () + elif attype == 'bit varying': + kwargs['varying'] = True + if charlen: + args = (int(charlen),) + else: + args = () elif attype in ('interval','interval year to month', 'interval day to second'): if charlen: diff --git a/test/dialect/test_postgresql.py b/test/dialect/test_postgresql.py index 020a92bf37..74f6c0e558 100644 --- a/test/dialect/test_postgresql.py +++ b/test/dialect/test_postgresql.py @@ -1617,11 +1617,11 @@ class TimePrecisionTest(TestBase, AssertsCompiledSQL): self.assert_compile(type_, expected) @testing.only_on('postgresql', 'DB specific feature') + @testing.provide_metadata def test_reflection(self): - m1 = MetaData(testing.db) t1 = Table( 't1', - m1, + metadata, Column('c1', postgresql.TIME()), Column('c2', postgresql.TIME(precision=5)), Column('c3', postgresql.TIME(timezone=True, precision=5)), @@ -1631,23 +1631,20 @@ class TimePrecisionTest(TestBase, AssertsCompiledSQL): precision=5)), ) t1.create() - try: - m2 = MetaData(testing.db) - t2 = Table('t1', m2, autoload=True) - eq_(t2.c.c1.type.precision, None) - eq_(t2.c.c2.type.precision, 5) - eq_(t2.c.c3.type.precision, 5) - eq_(t2.c.c4.type.precision, None) - eq_(t2.c.c5.type.precision, 5) - eq_(t2.c.c6.type.precision, 5) - eq_(t2.c.c1.type.timezone, False) - eq_(t2.c.c2.type.timezone, False) - eq_(t2.c.c3.type.timezone, True) - eq_(t2.c.c4.type.timezone, False) - eq_(t2.c.c5.type.timezone, False) - eq_(t2.c.c6.type.timezone, True) - finally: - t1.drop() + m2 = MetaData(testing.db) + t2 = Table('t1', m2, autoload=True) + eq_(t2.c.c1.type.precision, None) + eq_(t2.c.c2.type.precision, 5) + eq_(t2.c.c3.type.precision, 5) + eq_(t2.c.c4.type.precision, None) + eq_(t2.c.c5.type.precision, 5) + eq_(t2.c.c6.type.precision, 5) + eq_(t2.c.c1.type.timezone, False) + eq_(t2.c.c2.type.timezone, False) + eq_(t2.c.c3.type.timezone, True) + eq_(t2.c.c4.type.timezone, False) + eq_(t2.c.c5.type.timezone, False) + eq_(t2.c.c6.type.timezone, True) class ArrayTest(TestBase, AssertsExecutionResults): @@ -1966,7 +1963,7 @@ class ServerSideCursorsTest(TestBase, AssertsExecutionResults): finally: test_table.drop(checkfirst=True) -class SpecialTypesTest(TestBase, ComparesTables): +class SpecialTypesTest(TestBase, ComparesTables, AssertsCompiledSQL): """test DDL and reflection of PG-specific types """ __only_on__ = 'postgresql' @@ -1988,11 +1985,12 @@ class SpecialTypesTest(TestBase, ComparesTables): return "INTERVAL DAY TO SECOND" table = Table('sometable', metadata, - Column('id', postgresql.PGUuid, primary_key=True), - Column('flag', postgresql.PGBit), - Column('addr', postgresql.PGInet), - Column('addr2', postgresql.PGMacAddr), - Column('addr3', postgresql.PGCidr), + Column('id', postgresql.UUID, primary_key=True), + Column('flag', postgresql.BIT), + Column('bitstring', postgresql.BIT(4)), + Column('addr', postgresql.INET), + Column('addr2', postgresql.MACADDR), + Column('addr3', postgresql.CIDR), Column('doubleprec', postgresql.DOUBLE_PRECISION), Column('plain_interval', postgresql.INTERVAL), Column('year_interval', y2m()), @@ -2018,6 +2016,36 @@ class SpecialTypesTest(TestBase, ComparesTables): self.assert_tables_equal(table, t, strict_types=True) assert t.c.plain_interval.type.precision is None assert t.c.precision_interval.type.precision == 3 + assert t.c.bitstring.type.length == 4 + + def test_bit_compile(self): + pairs = [(postgresql.BIT(), 'BIT(1)'), + (postgresql.BIT(5), 'BIT(5)'), + (postgresql.BIT(varying=True), 'BIT VARYING'), + (postgresql.BIT(5, varying=True), 'BIT VARYING(5)'), + ] + for type_, expected in pairs: + self.assert_compile(type_, expected) + + @testing.provide_metadata + def test_bit_reflection(self): + t1 = Table('t1', metadata, + Column('bit1', postgresql.BIT()), + Column('bit5', postgresql.BIT(5)), + Column('bitvarying', postgresql.BIT(varying=True)), + Column('bitvarying5', postgresql.BIT(5, varying=True)), + ) + t1.create() + m2 = MetaData(testing.db) + t2 = Table('t1', m2, autoload=True) + eq_(t2.c.bit1.type.length, 1) + eq_(t2.c.bit1.type.varying, False) + eq_(t2.c.bit5.type.length, 5) + eq_(t2.c.bit5.type.varying, False) + eq_(t2.c.bitvarying.type.length, None) + eq_(t2.c.bitvarying.type.varying, True) + eq_(t2.c.bitvarying5.type.length, 5) + eq_(t2.c.bitvarying5.type.varying, True) class UUIDTest(TestBase): """Test the bind/return values of the UUID type.""" @@ -2211,4 +2239,3 @@ class TupleTest(TestBase): ).scalar(), exp ) -