From: Mike Bayer Date: Wed, 16 Mar 2011 18:06:33 +0000 (-0400) Subject: - Rewrote the query used to get the definition of a view, X-Git-Tag: rel_0_7b3~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=798339430a7657023188364c3ead0bcce56abd6b;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - Rewrote the query used to get the definition of a view, typically when using the Inspector interface, to use sys.sql_modules instead of the information schema, thereby allowing views definitions longer than 4000 characters to be fully returned. [ticket:2071] --- diff --git a/CHANGES b/CHANGES index e60ddd8fb6..9eedcae30b 100644 --- a/CHANGES +++ b/CHANGES @@ -498,6 +498,13 @@ CHANGES - Added RESERVED_WORDS informix dialect. [ticket:2092] +- mssql + - Rewrote the query used to get the definition of a view, + typically when using the Inspector interface, to + use sys.sql_modules instead of the information schema, + thereby allowing views definitions longer than 4000 + characters to be fully returned. [ticket:2071] + - mysql - oursql dialect accepts the same "ssl" arguments in create_engine() as that of MySQLdb. [ticket:2047] diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index c7fd20068f..77c736f208 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -130,14 +130,14 @@ which has triggers:: # ..., implicit_returning=False ) - + Declarative form:: class MyClass(Base): # ... __table_args__ = {'implicit_returning':False} - - + + This option can also be specified engine-wide using the ``implicit_returning=False`` argument on :func:`.create_engine`. @@ -1225,14 +1225,25 @@ class MSDialect(default.DefaultDialect): @reflection.cache def get_view_definition(self, connection, viewname, schema=None, **kw): current_schema = schema or self.default_schema_name - views = ischema.views - s = sql.select([views.c.view_definition], - sql.and_( - views.c.table_schema == current_schema, - views.c.table_name == viewname - ), + + rp = connection.execute( + sql.text( + "select definition from sys.sql_modules as mod, " + "sys.views as views, " + "sys.schemas as sch" + " where " + "mod.object_id=views.object_id and " + "views.schema_id=sch.schema_id and " + "views.name=:viewname and sch.name=:schname", + bindparams=[ + sql.bindparam('viewname', viewname, + sqltypes.String(convert_unicode=True)), + sql.bindparam('schname', current_schema, + sqltypes.String(convert_unicode=True)) + ] + ) ) - rp = connection.execute(s) + if rp: view_def = rp.scalar() return view_def diff --git a/test/dialect/test_mssql.py b/test/dialect/test_mssql.py index fbefcfed92..21a2fc322c 100644 --- a/test/dialect/test_mssql.py +++ b/test/dialect/test_mssql.py @@ -5,7 +5,7 @@ import os import re import warnings from sqlalchemy import * -from sqlalchemy import types, exc, schema +from sqlalchemy import types, exc, schema, event from sqlalchemy.orm import * from sqlalchemy.sql import table, column from sqlalchemy.databases import mssql @@ -15,6 +15,7 @@ from test.lib import * from test.lib.testing import eq_, emits_warning_on, \ assert_raises_message from sqlalchemy.util.compat import decimal +from sqlalchemy.engine.reflection import Inspector class CompileTest(TestBase, AssertsCompiledSQL): __dialect__ = mssql.dialect() @@ -1664,3 +1665,36 @@ class BinaryTest(TestBase, AssertsExecutionResults): stream = fp.read(len) fp.close() return stream + + +class ReflectHugeViewTest(TestBase): + def setup(self): + self.col_num = 150 + + self.metadata = MetaData(testing.db) + t = Table('base_table', self.metadata, + *[ + Column("long_named_column_number_%d" % i, Integer) + for i in xrange(self.col_num) + ] + ) + self.view_str = view_str = \ + "CREATE VIEW huge_named_view AS SELECT %s FROM base_table" % ( + ",".join("long_named_column_number_%d" % i + for i in xrange(self.col_num)) + ) + assert len(view_str) > 4000 + + event.listen(t, 'after_create', DDL(view_str) ) + event.listen(t, 'before_drop', DDL("DROP VIEW huge_named_view") ) + + self.metadata.create_all() + + def teardown(self): + self.metadata.drop_all() + + def test_inspect_view_definition(self): + inspector = Inspector.from_engine(testing.db) + view_def = inspector.get_view_definition("huge_named_view") + eq_(view_def, self.view_str) +