From 9ec6a9b8e336caf6ef79451f1154f40fc5e771a1 Mon Sep 17 00:00:00 2001 From: Robert Leftwich Date: Thu, 1 Dec 2005 12:51:38 +0000 Subject: [PATCH] Added float type to support real/double precision/float8/etc sql data types. Added columns.py as unit test. Modified sqlite.py, postgres.py and mysql.py to use the new type where appropriate (note -Oracle is unchanged at present). --- lib/sqlalchemy/databases/mysql.py | 5 +++ lib/sqlalchemy/databases/postgres.py | 9 +++++ lib/sqlalchemy/databases/sqlite.py | 2 ++ lib/sqlalchemy/types.py | 12 +++++-- test/alltests.py | 2 +- test/columns.py | 51 ++++++++++++++++++++++++++++ test/engines.py | 2 +- 7 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 test/columns.py diff --git a/lib/sqlalchemy/databases/mysql.py b/lib/sqlalchemy/databases/mysql.py index 45d85187a6..429ffc0fd0 100644 --- a/lib/sqlalchemy/databases/mysql.py +++ b/lib/sqlalchemy/databases/mysql.py @@ -33,6 +33,9 @@ except: class MSNumeric(sqltypes.Numeric): def get_col_spec(self): return "NUMERIC(%(precision)s, %(length)s)" % {'precision': self.precision, 'length' : self.length} +class MSFloat(sqltypes.Float): + def get_col_spec(self): + return "FLOAT(%(precision)s)" % {'precision': self.precision} class MSInteger(sqltypes.Integer): def get_col_spec(self): return "INTEGER" @@ -58,6 +61,7 @@ class MSBoolean(sqltypes.Boolean): colspecs = { sqltypes.Integer : MSInteger, sqltypes.Numeric : MSNumeric, + sqltypes.Float : MSFloat, sqltypes.DateTime : MSDateTime, sqltypes.String : MSString, sqltypes.Binary : MSBinary, @@ -72,6 +76,7 @@ ischema_names = { 'char' : MSChar, 'text' : MSText, 'decimal' : MSNumeric, + 'float' : MSFloat, 'timestamp' : MSDateTime, 'binary' : MSBinary, } diff --git a/lib/sqlalchemy/databases/postgres.py b/lib/sqlalchemy/databases/postgres.py index c8e742fe49..75b9e1aee3 100644 --- a/lib/sqlalchemy/databases/postgres.py +++ b/lib/sqlalchemy/databases/postgres.py @@ -36,6 +36,9 @@ except: class PGNumeric(sqltypes.Numeric): def get_col_spec(self): 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} class PGInteger(sqltypes.Integer): def get_col_spec(self): return "INTEGER" @@ -70,6 +73,7 @@ class PGBoolean(sqltypes.Boolean): pg2_colspecs = { sqltypes.Integer : PGInteger, sqltypes.Numeric : PGNumeric, + sqltypes.Float : PGFloat, sqltypes.DateTime : PG2DateTime, sqltypes.String : PGString, sqltypes.Binary : PGBinary, @@ -82,12 +86,17 @@ pg1_colspecs[sqltypes.DateTime] = PG1DateTime pg2_ischema_names = { 'integer' : PGInteger, + 'bigint' : PGInteger, 'character varying' : PGString, 'character' : PGChar, 'text' : PGText, 'numeric' : PGNumeric, + 'float' : PGFloat, + 'real' : PGFloat, + 'double precision' : PGFloat, 'timestamp without time zone' : PG2DateTime, 'bytea' : PGBinary, + 'boolean' : PGBoolean, } pg1_ischema_names = pg2_ischema_names.copy() pg1_ischema_names['timestamp without time zone'] = PG1DateTime diff --git a/lib/sqlalchemy/databases/sqlite.py b/lib/sqlalchemy/databases/sqlite.py index 1a00c555bc..845efdf33a 100644 --- a/lib/sqlalchemy/databases/sqlite.py +++ b/lib/sqlalchemy/databases/sqlite.py @@ -68,6 +68,7 @@ class SLBoolean(sqltypes.Boolean): colspecs = { sqltypes.Integer : SLInteger, sqltypes.Numeric : SLNumeric, + sqltypes.Float : SLNumeric, sqltypes.DateTime : SLDateTime, sqltypes.String : SLString, sqltypes.Binary : SLBinary, @@ -82,6 +83,7 @@ pragma_names = { 'CHAR' : SLChar, 'TEXT' : SLText, 'NUMERIC' : SLNumeric, + 'FLOAT' : SLNumeric, 'TIMESTAMP' : SLDateTime, 'BLOB' : SLBinary, } diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py index fc29f8056d..520e379a2d 100644 --- a/lib/sqlalchemy/types.py +++ b/lib/sqlalchemy/types.py @@ -17,7 +17,7 @@ __all__ = [ 'TypeEngine', 'TypeDecorator', 'NullTypeEngine', 'INT', 'CHAR', 'VARCHAR', 'TEXT', 'FLOAT', 'DECIMAL', - 'TIMESTAMP', 'DATETIME', 'CLOB', 'BLOB', 'BOOLEAN', 'String', 'Integer', 'Numeric', 'DateTime', 'Binary', 'Boolean', 'NULLTYPE' + 'TIMESTAMP', 'DATETIME', 'CLOB', 'BLOB', 'BOOLEAN', 'String', 'Integer', 'Numeric', 'Float', 'DateTime', 'Binary', 'Boolean', 'NULLTYPE' ] @@ -89,6 +89,12 @@ class Numeric(NullTypeEngine): def adapt(self, typeobj): return typeobj(self.precision, self.length) +class Float(NullTypeEngine): + def __init__(self, precision = 10): + self.precision = precision + def adapt(self, typeobj): + return typeobj(self.precision) + class DateTime(NullTypeEngine): pass @@ -98,7 +104,7 @@ class Binary(NullTypeEngine): class Boolean(NullTypeEngine): pass -class FLOAT(Numeric):pass +class FLOAT(Float):pass class TEXT(String):pass class DECIMAL(Numeric):pass class INT(Integer):pass @@ -111,4 +117,4 @@ class CHAR(String):pass class BLOB(Binary): pass class BOOLEAN(Boolean): pass -NULLTYPE = NullTypeEngine() \ No newline at end of file +NULLTYPE = NullTypeEngine() diff --git a/test/alltests.py b/test/alltests.py index 314e0eb986..c312cb1771 100644 --- a/test/alltests.py +++ b/test/alltests.py @@ -4,7 +4,7 @@ import unittest testbase.echo = False def suite(): - modules_to_test = ('attributes', 'historyarray', 'pool', 'engines', 'query', 'types', 'mapper', 'objectstore', 'dependency', 'sequence', 'select') + modules_to_test = ('attributes', 'historyarray', 'pool', 'engines', 'query', 'types', 'mapper', 'objectstore', 'dependency', 'sequence', 'select', 'columns') # modules_to_test = ('engines', 'mapper') alltests = unittest.TestSuite() for module in map(__import__, modules_to_test): diff --git a/test/columns.py b/test/columns.py new file mode 100644 index 0000000000..6196e15649 --- /dev/null +++ b/test/columns.py @@ -0,0 +1,51 @@ +from testbase import PersistTest +import testbase +import unittest, sys, datetime + +import sqlalchemy.databases.sqlite as sqllite + +from sqlalchemy import * + +class ColumnsTest(PersistTest): + + defaultExpectedResults = { 'int_column': 'int_column INTEGER', + 'varchar_column': 'varchar_column VARCHAR(20)', + 'numeric_column': 'numeric_column NUMERIC(12, 3)', + 'float_column': 'float_column NUMERIC(25, 2)' + } + + def setUp(self): + pass + + def _buildTestTable(self): + testTable = Table('testColumns', self.db, + Column('int_column', INT), + Column('varchar_column', VARCHAR(20)), + Column('numeric_column', Numeric(12,3)), + Column('float_column', FLOAT(25)), + ) + return testTable + + def _doTest(self, expectedResults): + testTable = self._buildTestTable() + for aCol in testTable.c: + self.assertEquals(expectedResults[aCol.name], self.db.schemagenerator(None).get_column_specification(aCol)) + + def testSqliteColumns(self): + self.db = create_engine('sqlite', {'filename':':memory:'}) + self._doTest(self.defaultExpectedResults) + + def testPostgresColumns(self): + self.db = engine.create_engine('postgres', {'database':'test', 'host':'127.0.0.1', 'user':'scott', 'password':'tiger'}, echo=False) + expectedResults = self.defaultExpectedResults.copy() + expectedResults['float_column'] = 'float_column FLOAT(25)' + self._doTest(expectedResults) + + def testMySqlColumns(self): + self.db = engine.create_engine('mysql', {'db':'test', 'host':'127.0.0.1', 'user':'scott', 'passwd':'tiger'}, echo=False) + expectedResults = self.defaultExpectedResults.copy() + expectedResults['float_column'] = 'float_column FLOAT(25)' + self._doTest(expectedResults) + +if __name__ == "__main__": + unittest.main() diff --git a/test/engines.py b/test/engines.py index d2fd10962c..c84df433e5 100644 --- a/test/engines.py +++ b/test/engines.py @@ -17,7 +17,7 @@ class EngineTest(PersistTest): Column('user_id', INT, primary_key = True), Column('user_name', VARCHAR(20), nullable = False), Column('test1', CHAR(5), nullable = False), - Column('test2', FLOAT(5,5), nullable = False), + Column('test2', FLOAT(5), nullable = False), Column('test3', TEXT), Column('test4', DECIMAL, nullable = False), Column('test5', TIMESTAMP), -- 2.47.2