From: Mike Bayer Date: Mon, 3 Apr 2006 01:35:48 +0000 (+0000) Subject: merged Rick Morrison / Runar Petursson's MS-SQL module, with adjustments to alias... X-Git-Tag: rel_0_1_6~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c026339ad81dc3fc225330e9c1d383821b4e29de;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git merged Rick Morrison / Runar Petursson's MS-SQL module, with adjustments to alias schema-qualified Table objects --- diff --git a/lib/sqlalchemy/databases/__init__.py b/lib/sqlalchemy/databases/__init__.py index 10cf9f6b22..f009034c75 100644 --- a/lib/sqlalchemy/databases/__init__.py +++ b/lib/sqlalchemy/databases/__init__.py @@ -5,4 +5,4 @@ # the MIT License: http://www.opensource.org/licenses/mit-license.php -__all__ = ['oracle', 'postgres', 'sqlite', 'mysql'] \ No newline at end of file +__all__ = ['oracle', 'postgres', 'sqlite', 'mysql', 'mssql'] diff --git a/lib/sqlalchemy/databases/information_schema.py b/lib/sqlalchemy/databases/information_schema.py index feb3cf0c52..468e9a5486 100644 --- a/lib/sqlalchemy/databases/information_schema.py +++ b/lib/sqlalchemy/databases/information_schema.py @@ -56,6 +56,18 @@ gen_key_constraints = schema.Table("key_column_usage", generic_engine, Column("constraint_name", String), schema="information_schema") +gen_ref_constraints = schema.Table("referential_constraints", generic_engine, + Column("constraint_catalog", String), + Column("constraint_schema", String), + Column("constraint_name", String), + Column("unique_constraint_catlog", String), + Column("unique_constraint_schema", String), + Column("unique_constraint_name", String), + Column("match_option", String), + Column("update_rule", String), + Column("delete_rule", String), + schema="information_schema") + class ISchema(object): def __init__(self, engine): self.engine = engine diff --git a/lib/sqlalchemy/engine.py b/lib/sqlalchemy/engine.py index 55bad6abd9..727ee30ad2 100644 --- a/lib/sqlalchemy/engine.py +++ b/lib/sqlalchemy/engine.py @@ -193,7 +193,7 @@ class SQLSession(object): connection = property(_connection, doc="the connection represented by this SQLSession. The connection is late-connecting, meaning the call to the connection pool only occurs when it is first called (and the pool will typically only connect the first time it is called as well)") def begin(self): - """begins" a transaction on this SQLSession's connection. repeated calls to begin() will increment a counter that must be decreased by corresponding commit() statements before an actual commit occurs. this is to provide "nested" behavior of transactions so that different functions in a particular call stack can call begin()/commit() independently of each other without knowledge of an existing transaction.""" + """begins a transaction on this SQLSession's connection. repeated calls to begin() will increment a counter that must be decreased by corresponding commit() statements before an actual commit occurs. this is to provide "nested" behavior of transactions so that different functions in a particular call stack can call begin()/commit() independently of each other without knowledge of an existing transaction. """ if self.__tcount == 0: self.__transaction = self.connection self.engine.do_begin(self.connection) @@ -506,7 +506,7 @@ class SQLEngine(schema.SchemaEngine): self.commit() def begin(self): - """"begins a transaction on the current thread's SQLSession.""" + """ begins a transaction on the current thread SQLSession. """ self.session.begin() def rollback(self): @@ -647,7 +647,7 @@ class SQLEngine(schema.SchemaEngine): return ResultProxy(cursor, self, typemap=compiled.typemap) def execute(self, statement, parameters=None, connection=None, cursor=None, echo=None, typemap=None, commit=False, return_raw=False, **kwargs): - """executes the given string-based SQL statement with the given parameters. + """ executes the given string-based SQL statement with the given parameters. The parameters can be a dictionary or a list, or a list of dictionaries or lists, depending on the paramstyle of the DBAPI. @@ -659,7 +659,7 @@ class SQLEngine(schema.SchemaEngine): up. In all error cases, a rollback() is immediately performed on the connection before - propigating the exception outwards. + propagating the exception outwards. Other options include: diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index 756c03b6ef..eabfee9bb7 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -256,7 +256,7 @@ class Column(sql.ColumnClause, SchemaItem): default=None : a scalar, python callable, or ClauseElement representing the "default value" for this column, which will be invoked upon insert if this column is not present in the insert list or is given a value of None. - + hidden=False : indicates this column should not be listed in the table's list of columns. Used for the "oid" column, which generally isnt in column lists. @@ -271,7 +271,9 @@ class Column(sql.ColumnClause, SchemaItem): indexed in a unique index . Pass true to autogenerate the index name. Pass a string to specify the index name. Multiple columns that specify the same index name will all be included in the index, in the - order of their creation. """ + order of their creation. + + """ name = str(name) # in case of incoming unicode super(Column, self).__init__(name, None, type) @@ -507,6 +509,7 @@ class Sequence(DefaultGenerator): """calls the visit_seauence method on the given visitor.""" return visitor.visit_sequence(self) + class Index(SchemaItem): """Represents an index of columns from a database table """ diff --git a/test/indexes.py b/test/indexes.py index 17c2e7dc67..7ad008f5dc 100644 --- a/test/indexes.py +++ b/test/indexes.py @@ -42,9 +42,10 @@ class IndexTest(testbase.AssertMixin): """test that mixed-case index identifiers are legal""" employees = Table('companyEmployees', testbase.db, Column('id', Integer, primary_key=True), - Column('firstName', String), - Column('lastName', String), - Column('emailAddress', String)) + Column('firstName', String(30)), + Column('lastName', String(30)), + Column('emailAddress', String(30))) + employees.create() self.created.append(employees) diff --git a/test/select.py b/test/select.py index 9c260c3243..0fc406e4a6 100644 --- a/test/select.py +++ b/test/select.py @@ -6,6 +6,7 @@ import sqlalchemy.databases.oracle as oracle import sqlalchemy.databases.sqlite as sqlite db = ansisql.engine() +#db = create_engine('mssql') from testbase import PersistTest import unittest, re @@ -595,6 +596,7 @@ class CRUDTest(SQLTest): class SchemaTest(SQLTest): def testselect(self): + # these tests will fail with the MS-SQL compiler since it will alias schema-qualified tables self.runtest(table4.select(), "SELECT remotetable.rem_id, remotetable.datatype_id, remotetable.value FROM remote_owner.remotetable") self.runtest(table4.select(and_(table4.c.datatype_id==7, table4.c.value=='hi')), "SELECT remotetable.rem_id, remotetable.datatype_id, remotetable.value FROM remote_owner.remotetable WHERE remotetable.datatype_id = :remotetable_datatype_id AND remotetable.value = :remotetable_value") diff --git a/test/testbase.py b/test/testbase.py index 1578be5a0c..923ed7de99 100644 --- a/test/testbase.py +++ b/test/testbase.py @@ -46,9 +46,11 @@ def parse_argv(): elif DBTYPE == 'oracle8': db_uri = 'oracle://user=scott&password=tiger' opts = {'use_ansi':False} + elif DBTYPE == 'mssql': + db_uri = 'mssql://database=test&user=scott&password=tiger' if not db_uri: - raise "Could not create engine. specify --db to test runner." + raise "Could not create engine. specify --db to test runner." if PROXY: db = proxy.ProxyEngine(echo=echo, default_ordering=True, **opts) diff --git a/test/testtypes.py b/test/testtypes.py index 708b38a281..c2e3043c99 100644 --- a/test/testtypes.py +++ b/test/testtypes.py @@ -147,8 +147,8 @@ class BinaryTest(AssertMixin): def testbinary(self): stream1 =self.get_module_stream('sqlalchemy.sql') stream2 =self.get_module_stream('sqlalchemy.engine') - binary_table.insert().execute(misc='sql.pyc', data=stream1, data_slice=stream1[0:100]) - binary_table.insert().execute(misc='engine.pyc', data=stream2, data_slice=stream2[0:99]) + binary_table.insert().execute(primary_id=1, misc='sql.pyc', data=stream1, data_slice=stream1[0:100]) + binary_table.insert().execute(primary_id=2, misc='engine.pyc', data=stream2, data_slice=stream2[0:99]) l = binary_table.select().execute().fetchall() print len(stream1), len(l[0]['data']), len(l[0]['data_slice']) self.assert_(list(stream1) == list(l[0]['data'])) @@ -179,7 +179,7 @@ class DateTest(AssertMixin): collist = [Column('user_id', INT, primary_key = True), Column('user_name', VARCHAR(20)), Column('user_datetime', DateTime), Column('user_date', Date), Column('user_time', Time)] - if db.engine.__module__.endswith('mysql'): + if db.engine.__module__.endswith('mysql') or db.engine.__module__.endswith('mssql'): # strip microseconds -- not supported by this engine (should be an easier way to detect this) for d in insert_data: if d[2] is not None: @@ -198,6 +198,7 @@ class DateTest(AssertMixin): users_with_date = Table('query_users_with_date', db, redefine = True, *collist) users_with_date.create() insert_dicts = [dict(zip(fnames, d)) for d in insert_data] + for idict in insert_dicts: users_with_date.insert().execute(**idict) # insert the data