From: Mike Bayer Date: Sat, 9 Dec 2006 03:21:18 +0000 (+0000) Subject: - support for None as precision/length in numeric types for postgres, sqlite, mysql X-Git-Tag: rel_0_3_2~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d56a50eb7056cfe054c03b47db3d79dab03a5638;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - support for None as precision/length in numeric types for postgres, sqlite, mysql - postgres reflection fixes: [ticket:349] [ticket:382] --- diff --git a/CHANGES b/CHANGES index 8614d8dde8..21a2307cd1 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,7 @@ accidentally [ticket:387] to have it be weak referencing, use create_session(weak_identity_map=True) - MySQL detects errors 2006 (server has gone away) and 2014 (commands out of sync) and invalidates the connection on which it occured. +- postgres reflection fixes: [ticket:349] [ticket:382] - added keywords for EXCEPT, INTERSECT, EXCEPT ALL, INTERSECT ALL [ticket:247] - assign_mapper in assignmapper extension returns the created mapper diff --git a/lib/sqlalchemy/databases/mysql.py b/lib/sqlalchemy/databases/mysql.py index 662d276e93..b87e2d6e94 100644 --- a/lib/sqlalchemy/databases/mysql.py +++ b/lib/sqlalchemy/databases/mysql.py @@ -29,7 +29,10 @@ class MSNumeric(sqltypes.Numeric): self.zerofill = 'zerofill' in kw super(MSNumeric, self).__init__(precision, length) def get_col_spec(self): - return kw_colspec(self, "NUMERIC(%(precision)s, %(length)s)" % {'precision': self.precision, 'length' : self.length}) + if self.precision is None: + return kw_colspec(self, "NUMERIC") + else: + return kw_colspec(self, "NUMERIC(%(precision)s, %(length)s)" % {'precision': self.precision, 'length' : self.length}) class MSDecimal(MSNumeric): def get_col_spec(self): if self.precision is not None and self.length is not None: diff --git a/lib/sqlalchemy/databases/postgres.py b/lib/sqlalchemy/databases/postgres.py index 5c78e2f520..a3ecab8253 100644 --- a/lib/sqlalchemy/databases/postgres.py +++ b/lib/sqlalchemy/databases/postgres.py @@ -34,10 +34,16 @@ except: class PGNumeric(sqltypes.Numeric): def get_col_spec(self): - return "NUMERIC(%(precision)s, %(length)s)" % {'precision': self.precision, 'length' : self.length} + if not self.precision: + return "NUMERIC" + else: + return "NUMERIC(%(precision)s, %(length)s)" % {'precision': self.precision, 'length' : self.length} class PGFloat(sqltypes.Float): def get_col_spec(self): - return "FLOAT(%(precision)s)" % {'precision': self.precision} + if not self.precision: + return "FLOAT" + else: + return "FLOAT(%(precision)s)" % {'precision': self.precision} class PGInteger(sqltypes.Integer): def get_col_spec(self): return "INTEGER" @@ -345,24 +351,29 @@ class PGDialect(ansisql.ANSIDialect): try: charlen = re.search('\(([\d,]+)\)',row['format_type']).group(1) except: - charlen = None + charlen = False - numericprec = None - numericscale = None + numericprec = False + numericscale = False default = row['default'] if attype == 'numeric': - numericprec, numericscale = charlen.split(',') - charlen = None + if charlen is False: + numericprec, numericscale = (None, None) + else: + numericprec, numericscale = charlen.split(',') + charlen = False if attype == 'double precision': numericprec, numericscale = (53, None) - charlen = None + charlen = False if attype == 'integer': numericprec, numericscale = (32, 0) - charlen = None + charlen = False args = [] for a in (charlen, numericprec, numericscale): - if a is not None: + if a is None: + args.append(None) + elif a is not False: args.append(int(a)) kwargs = {} @@ -421,22 +432,15 @@ class PGDialect(ansisql.ANSIDialect): if row is None: break - identifier = '(?:[a-z_][a-z0-9_$]+|"(?:[^"]|"")+")' - identifier_group = '%s(?:, %s)*' % (identifier, identifier) - identifiers = '(%s)(?:, (%s))*' % (identifier, identifier) - f = re.compile(identifiers) - # FOREIGN KEY (mail_user_id,"Mail_User_ID2") REFERENCES "mYschema".euro_user(user_id,"User_ID2") - foreign_key_pattern = 'FOREIGN KEY \((%s)\) REFERENCES (?:(%s)\.)?(%s)\((%s)\)' % (identifier_group, identifier, identifier, identifier_group) - p = re.compile(foreign_key_pattern) - - m = p.search(row['condef']) + foreign_key_pattern = 'FOREIGN KEY \((.*?)\) REFERENCES (?:(.*?)\.)?(.*?)\((.*?)\)' + m = re.search(foreign_key_pattern, row['condef']) (constrained_columns, referred_schema, referred_table, referred_columns) = m.groups() - constrained_columns = [preparer._unquote_identifier(x) for x in f.search(constrained_columns).groups() if x] + constrained_columns = [preparer._unquote_identifier(x) for x in re.split(r'\s*,\s*', constrained_columns)] if referred_schema: referred_schema = preparer._unquote_identifier(referred_schema) referred_table = preparer._unquote_identifier(referred_table) - referred_columns = [preparer._unquote_identifier(x) for x in f.search(referred_columns).groups() if x] + referred_columns = [preparer._unquote_identifier(x) for x in re.split(r'\s*,\s', referred_columns)] refspec = [] if referred_schema is not None: diff --git a/lib/sqlalchemy/databases/sqlite.py b/lib/sqlalchemy/databases/sqlite.py index 4eee8e4d03..6300250b34 100644 --- a/lib/sqlalchemy/databases/sqlite.py +++ b/lib/sqlalchemy/databases/sqlite.py @@ -27,7 +27,10 @@ except ImportError: class SLNumeric(sqltypes.Numeric): def get_col_spec(self): - return "NUMERIC(%(precision)s, %(length)s)" % {'precision': self.precision, 'length' : self.length} + if self.precision is None: + return "NUMERIC" + else: + return "NUMERIC(%(precision)s, %(length)s)" % {'precision': self.precision, 'length' : self.length} class SLInteger(sqltypes.Integer): def get_col_spec(self): return "INTEGER" diff --git a/test/engine/reflection.py b/test/engine/reflection.py index 6c367159b4..3467c6ae42 100644 --- a/test/engine/reflection.py +++ b/test/engine/reflection.py @@ -49,6 +49,7 @@ class ReflectionTest(PersistTest): Column('test_passivedefault2', Integer, PassiveDefault("5")), Column('test_passivedefault3', deftype2, PassiveDefault(defval2)), Column('test9', Binary(100)), + Column('test_numeric', Numeric(None, None)), mysql_engine='InnoDB' ) @@ -58,7 +59,8 @@ class ReflectionTest(PersistTest): Column('email_address', String(20)), mysql_engine='InnoDB' ) - + meta.drop_all() + users.create() addresses.create() @@ -169,7 +171,6 @@ class ReflectionTest(PersistTest): autoload=True) u2 = Table('users', meta2, autoload=True) - print "ITS", list(a2.primary_key) assert list(a2.primary_key) == [a2.c.id] assert list(u2.primary_key) == [u2.c.id] assert u2.join(a2).onclause == u2.c.id==a2.c.id @@ -304,6 +305,7 @@ class ReflectionTest(PersistTest): 'multi', meta, Column('multi_id', Integer, primary_key=True), Column('multi_rev', Integer, primary_key=True), + Column('multi_hoho', Integer, primary_key=True), Column('name', String(50), nullable=False), Column('val', String(100)), mysql_engine='InnoDB' @@ -312,10 +314,12 @@ class ReflectionTest(PersistTest): Column('id', Integer, primary_key=True), Column('foo', Integer), Column('bar', Integer), + Column('lala', Integer), Column('data', String(50)), - ForeignKeyConstraint(['foo', 'bar'], ['multi.multi_id', 'multi.multi_rev']), + ForeignKeyConstraint(['foo', 'bar', 'lala'], ['multi.multi_id', 'multi.multi_rev', 'multi.multi_hoho']), mysql_engine='InnoDB' ) + assert table.c.multi_hoho meta.create_all() meta.clear() @@ -327,11 +331,10 @@ class ReflectionTest(PersistTest): print table2 j = join(table, table2) print str(j.onclause) - self.assert_(and_(table.c.multi_id==table2.c.foo, table.c.multi_rev==table2.c.bar).compare(j.onclause)) + self.assert_(and_(table.c.multi_id==table2.c.foo, table.c.multi_rev==table2.c.bar, table.c.multi_hoho==table2.c.lala).compare(j.onclause)) finally: - pass -# meta.drop_all() + meta.drop_all() def testcheckfirst(self): meta = BoundMetaData(testbase.db)