diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-12-03 14:04:05 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-12-06 18:27:19 -0500 |
| commit | 22deafe15289d2be55682e1632016004b02b62c0 (patch) | |
| tree | 5b521531418aebd4e293f848ebe4accbbd9bc5bc /test | |
| parent | e88dc004e6bcd1418cb8eb811d0aa580c2a44b8f (diff) | |
| download | sqlalchemy-22deafe15289d2be55682e1632016004b02b62c0.tar.gz | |
Warn when caching is disabled / document
This patch adds new warnings for all elements that
don't indicate their caching behavior, including user-defined
ClauseElement subclasses and third party dialects.
it additionally adds new documentation to discuss an apparent
performance degradation in 1.4 when caching is disabled as a
result in the significant expense incurred by ORM
lazy loaders, which in 1.3 used BakedQuery so were actually
cached.
As a result of adding the warnings, a fair degree of
lesser used SQL expression objects identified that they did not
define caching behavior so would have been producing
``[no key]``, including PostgreSQL constructs ``hstore``
and ``array``. These have been amended to use inherit
cache where appropriate. "on conflict" constructs in
PostgreSQL, MySQL, SQLite still explicitly don't generate
a cache key at this time.
The change also adds a test for all constructs via
assert_compile() to assert they will not generate cache
warnings.
Fixes: #7394
Change-Id: I85958affbb99bfad0f5efa21bc8f2a95e7e46981
Diffstat (limited to 'test')
| -rw-r--r-- | test/dialect/mssql/test_compiler.py | 2 | ||||
| -rw-r--r-- | test/engine/test_execute.py | 1 | ||||
| -rw-r--r-- | test/ext/test_baked.py | 1 | ||||
| -rw-r--r-- | test/ext/test_compiler.py | 30 | ||||
| -rw-r--r-- | test/orm/inheritance/test_assorted_poly.py | 2 | ||||
| -rw-r--r-- | test/orm/test_cache_key.py | 30 | ||||
| -rw-r--r-- | test/orm/test_lambdas.py | 2 | ||||
| -rw-r--r-- | test/orm/test_query.py | 2 | ||||
| -rw-r--r-- | test/sql/test_compare.py | 79 | ||||
| -rw-r--r-- | test/sql/test_functions.py | 20 | ||||
| -rw-r--r-- | test/sql/test_labels.py | 2 | ||||
| -rw-r--r-- | test/sql/test_lambdas.py | 25 | ||||
| -rw-r--r-- | test/sql/test_operators.py | 8 | ||||
| -rw-r--r-- | test/sql/test_resultset.py | 2 | ||||
| -rw-r--r-- | test/sql/test_types.py | 2 |
15 files changed, 186 insertions, 22 deletions
diff --git a/test/dialect/mssql/test_compiler.py b/test/dialect/mssql/test_compiler.py index e9ff8fb19..74722e949 100644 --- a/test/dialect/mssql/test_compiler.py +++ b/test/dialect/mssql/test_compiler.py @@ -180,7 +180,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): t.update() .where(t.c.somecolumn == "q") .values(somecolumn="x") - .with_hint("XYZ", "mysql"), + .with_hint("XYZ", dialect_name="mysql"), "UPDATE sometable SET somecolumn=:somecolumn " "WHERE sometable.somecolumn = :somecolumn_1", ) diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py index 317d0b692..fb4fd02a1 100644 --- a/test/engine/test_execute.py +++ b/test/engine/test_execute.py @@ -3865,6 +3865,7 @@ class DialectDoesntSupportCachingTest(fixtures.TestBase): class MyDialect(SQLiteDialect_pysqlite): statement_compiler = MyCompiler + supports_statement_cache = False from sqlalchemy.dialects import registry diff --git a/test/ext/test_baked.py b/test/ext/test_baked.py index c40ee3395..b3d6ebec2 100644 --- a/test/ext/test_baked.py +++ b/test/ext/test_baked.py @@ -1043,6 +1043,7 @@ class CustomIntegrationTest(testing.AssertsCompiledSQL, BakedTest): from sqlalchemy.orm.interfaces import UserDefinedOption class RelationshipCache(UserDefinedOption): + inherit_cache = True propagate_to_loaders = True diff --git a/test/ext/test_compiler.py b/test/ext/test_compiler.py index 7fb021329..996797122 100644 --- a/test/ext/test_compiler.py +++ b/test/ext/test_compiler.py @@ -37,6 +37,8 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): def test_column(self): class MyThingy(ColumnClause): + inherit_cache = False + def __init__(self, arg=None): super(MyThingy, self).__init__(arg or "MYTHINGY!") @@ -96,7 +98,7 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): def test_no_compile_for_col_label(self): class MyThingy(FunctionElement): - pass + inherit_cache = True @compiles(MyThingy) def visit_thingy(thingy, compiler, **kw): @@ -120,6 +122,8 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): def test_stateful(self): class MyThingy(ColumnClause): + inherit_cache = False + def __init__(self): super(MyThingy, self).__init__("MYTHINGY!") @@ -142,6 +146,8 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): def test_callout_to_compiler(self): class InsertFromSelect(ClauseElement): + inherit_cache = False + def __init__(self, table, select): self.table = table self.select = select @@ -162,7 +168,7 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): def test_no_default_but_has_a_visit(self): class MyThingy(ColumnClause): - pass + inherit_cache = False @compiles(MyThingy, "postgresql") def visit_thingy(thingy, compiler, **kw): @@ -172,7 +178,7 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): def test_no_default_has_no_visit(self): class MyThingy(TypeEngine): - pass + inherit_cache = False @compiles(MyThingy, "postgresql") def visit_thingy(thingy, compiler, **kw): @@ -189,6 +195,7 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): @testing.combinations((True,), (False,)) def test_no_default_proxy_generation(self, named): class my_function(FunctionElement): + inherit_cache = False if named: name = "my_function" type = Numeric() @@ -215,7 +222,7 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): def test_no_default_message(self): class MyThingy(ClauseElement): - pass + inherit_cache = False @compiles(MyThingy, "postgresql") def visit_thingy(thingy, compiler, **kw): @@ -314,7 +321,7 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): from sqlalchemy.dialects import postgresql class MyUtcFunction(FunctionElement): - pass + inherit_cache = True @compiles(MyUtcFunction) def visit_myfunc(element, compiler, **kw): @@ -335,7 +342,7 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): def test_functions_args_noname(self): class myfunc(FunctionElement): - pass + inherit_cache = True @compiles(myfunc) def visit_myfunc(element, compiler, **kw): @@ -351,6 +358,7 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): class greatest(FunctionElement): type = Numeric() name = "greatest" + inherit_cache = True @compiles(greatest) def default_greatest(element, compiler, **kw): @@ -380,12 +388,15 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): def test_function_subclasses_one(self): class Base(FunctionElement): + inherit_cache = True name = "base" class Sub1(Base): + inherit_cache = True name = "sub1" class Sub2(Base): + inherit_cache = True name = "sub2" @compiles(Base) @@ -407,6 +418,7 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): name = "base" class Sub1(Base): + inherit_cache = True name = "sub1" @compiles(Base) @@ -414,9 +426,11 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): return element.name class Sub2(Base): + inherit_cache = True name = "sub2" class SubSub1(Sub1): + inherit_cache = True name = "subsub1" self.assert_compile( @@ -545,7 +559,7 @@ class ExecuteTest(fixtures.TablesTest): @testing.fixture() def insert_fixture(self): class MyInsert(Executable, ClauseElement): - pass + inherit_cache = True @compiles(MyInsert) def _run_myinsert(element, compiler, **kw): @@ -556,7 +570,7 @@ class ExecuteTest(fixtures.TablesTest): @testing.fixture() def select_fixture(self): class MySelect(Executable, ClauseElement): - pass + inherit_cache = True @compiles(MySelect) def _run_myinsert(element, compiler, **kw): diff --git a/test/orm/inheritance/test_assorted_poly.py b/test/orm/inheritance/test_assorted_poly.py index 66a722ccf..f51fb17a4 100644 --- a/test/orm/inheritance/test_assorted_poly.py +++ b/test/orm/inheritance/test_assorted_poly.py @@ -2252,7 +2252,7 @@ class ColSubclassTest( id = Column(Integer, primary_key=True) class MySpecialColumn(Column): - pass + inherit_cache = True class B(A): __tablename__ = "b" diff --git a/test/orm/test_cache_key.py b/test/orm/test_cache_key.py index 5ed856a3c..e3ba870f2 100644 --- a/test/orm/test_cache_key.py +++ b/test/orm/test_cache_key.py @@ -26,6 +26,7 @@ from sqlalchemy.orm import relationship from sqlalchemy.orm import selectinload from sqlalchemy.orm import Session from sqlalchemy.orm import subqueryload +from sqlalchemy.orm import synonym from sqlalchemy.orm import with_expression from sqlalchemy.orm import with_loader_criteria from sqlalchemy.orm import with_polymorphic @@ -387,6 +388,35 @@ class CacheKeyTest(CacheKeyFixture, _fixtures.FixtureTest): compare_values=True, ) + def test_synonyms(self, registry): + """test for issue discovered in #7394""" + + @registry.mapped + class User2(object): + __table__ = self.tables.users + + name_syn = synonym("name") + + @registry.mapped + class Address2(object): + __table__ = self.tables.addresses + + name_syn = synonym("email_address") + + self._run_cache_key_fixture( + lambda: ( + User2.id, + User2.name, + User2.name_syn, + Address2.name_syn, + Address2.email_address, + aliased(User2).name_syn, + aliased(User2, name="foo").name_syn, + aliased(User2, name="bar").name_syn, + ), + compare_values=True, + ) + def test_more_with_entities_sanity_checks(self): """test issue #6503""" User, Address, Keyword, Order, Item = self.classes( diff --git a/test/orm/test_lambdas.py b/test/orm/test_lambdas.py index 53766c434..7373093ee 100644 --- a/test/orm/test_lambdas.py +++ b/test/orm/test_lambdas.py @@ -219,7 +219,7 @@ class LambdaTest(QueryTest, AssertsCompiledSQL): assert_raises_message( exc.ArgumentError, - "Cacheable Core or ORM object expected, got", + "ExecutionOption Core or ORM object expected, got", select(lambda: User).options, lambda: subqueryload(User.addresses), ) diff --git a/test/orm/test_query.py b/test/orm/test_query.py index 32a46463d..4cce3f33f 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -2112,6 +2112,7 @@ class ExpressionTest(QueryTest, AssertsCompiledSQL): class max_(expression.FunctionElement): name = "max" + inherit_cache = True @compiles(max_) def visit_max(element, compiler, **kw): @@ -2126,6 +2127,7 @@ class ExpressionTest(QueryTest, AssertsCompiledSQL): class not_named_max(expression.ColumnElement): name = "not_named_max" + inherit_cache = True @compiles(not_named_max) def visit_max(element, compiler, **kw): diff --git a/test/sql/test_compare.py b/test/sql/test_compare.py index af78ea19b..ca1eff62b 100644 --- a/test/sql/test_compare.py +++ b/test/sql/test_compare.py @@ -16,6 +16,7 @@ from sqlalchemy import Integer from sqlalchemy import literal_column from sqlalchemy import MetaData from sqlalchemy import or_ +from sqlalchemy import PickleType from sqlalchemy import select from sqlalchemy import String from sqlalchemy import Table @@ -1264,13 +1265,20 @@ class CacheKeyTest(CacheKeyFixture, CoreFixtures, fixtures.TestBase): # the None for cache key will prevent objects # which contain these elements from being cached. f1 = Foobar1() - eq_(f1._generate_cache_key(), None) + with expect_warnings( + "Class Foobar1 will not make use of SQL compilation caching" + ): + eq_(f1._generate_cache_key(), None) f2 = Foobar2() - eq_(f2._generate_cache_key(), None) + with expect_warnings( + "Class Foobar2 will not make use of SQL compilation caching" + ): + eq_(f2._generate_cache_key(), None) s1 = select(column("q"), Foobar2()) + # warning is memoized, won't happen the second time eq_(s1._generate_cache_key(), None) def test_get_children_no_method(self): @@ -1355,6 +1363,7 @@ class CompareAndCopyTest(CoreFixtures, fixtures.TestBase): and ( "__init__" in cls.__dict__ or issubclass(cls, AliasedReturnsRows) + or "inherit_cache" not in cls.__dict__ ) and not issubclass(cls, (Annotated)) and "orm" not in cls.__module__ @@ -1819,3 +1828,69 @@ class TypesTest(fixtures.TestBase): eq_(c1, c2) ne_(c1, c3) eq_(c1, c4) + + def test_thirdparty_sub_subclass_no_cache(self): + class MyType(PickleType): + pass + + expr = column("q", MyType()) == 1 + + with expect_warnings( + r"TypeDecorator MyType\(\) will not produce a cache key" + ): + is_(expr._generate_cache_key(), None) + + def test_userdefined_sub_subclass_no_cache(self): + class MyType(UserDefinedType): + cache_ok = True + + class MySubType(MyType): + pass + + expr = column("q", MySubType()) == 1 + + with expect_warnings( + r"UserDefinedType MySubType\(\) will not produce a cache key" + ): + is_(expr._generate_cache_key(), None) + + def test_userdefined_sub_subclass_cache_ok(self): + class MyType(UserDefinedType): + cache_ok = True + + class MySubType(MyType): + cache_ok = True + + def go1(): + expr = column("q", MySubType()) == 1 + return expr + + def go2(): + expr = column("p", MySubType()) == 1 + return expr + + c1 = go1()._generate_cache_key()[0] + c2 = go1()._generate_cache_key()[0] + c3 = go2()._generate_cache_key()[0] + + eq_(c1, c2) + ne_(c1, c3) + + def test_thirdparty_sub_subclass_cache_ok(self): + class MyType(PickleType): + cache_ok = True + + def go1(): + expr = column("q", MyType()) == 1 + return expr + + def go2(): + expr = column("p", MyType()) == 1 + return expr + + c1 = go1()._generate_cache_key()[0] + c2 = go1()._generate_cache_key()[0] + c3 = go2()._generate_cache_key()[0] + + eq_(c1, c2) + ne_(c1, c3) diff --git a/test/sql/test_functions.py b/test/sql/test_functions.py index 9378cfc38..e08526419 100644 --- a/test/sql/test_functions.py +++ b/test/sql/test_functions.py @@ -81,6 +81,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): # test generic function compile class fake_func(GenericFunction): + inherit_cache = True __return_type__ = sqltypes.Integer def __init__(self, arg, **kwargs): @@ -107,6 +108,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): if use_custom: class MyFunc(FunctionElement): + inherit_cache = True name = "myfunc" type = Integer() @@ -135,6 +137,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): def test_use_labels_function_element(self): class max_(FunctionElement): name = "max" + inherit_cache = True @compiles(max_) def visit_max(element, compiler, **kw): @@ -260,7 +263,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): def test_custom_default_namespace(self): class myfunc(GenericFunction): - pass + inherit_cache = True assert isinstance(func.myfunc(), myfunc) self.assert_compile(func.myfunc(), "myfunc()") @@ -268,6 +271,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): def test_custom_type(self): class myfunc(GenericFunction): type = DateTime + inherit_cache = True assert isinstance(func.myfunc().type, DateTime) self.assert_compile(func.myfunc(), "myfunc()") @@ -275,12 +279,14 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): def test_custom_legacy_type(self): # in case someone was using this system class myfunc(GenericFunction): + inherit_cache = True __return_type__ = DateTime assert isinstance(func.myfunc().type, DateTime) def test_case_sensitive(self): class MYFUNC(GenericFunction): + inherit_cache = True type = DateTime assert isinstance(func.MYFUNC().type, DateTime) @@ -336,6 +342,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): def test_custom_w_custom_name(self): class myfunc(GenericFunction): + inherit_cache = True name = "notmyfunc" assert isinstance(func.notmyfunc(), myfunc) @@ -343,6 +350,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): def test_custom_w_quoted_name(self): class myfunc(GenericFunction): + inherit_cache = True name = quoted_name("NotMyFunc", quote=True) identifier = "myfunc" @@ -350,6 +358,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): def test_custom_w_quoted_name_no_identifier(self): class myfunc(GenericFunction): + inherit_cache = True name = quoted_name("NotMyFunc", quote=True) # note this requires that the quoted name be lower cased for @@ -359,6 +368,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): def test_custom_package_namespace(self): def cls1(pk_name): class myfunc(GenericFunction): + inherit_cache = True package = pk_name return myfunc @@ -372,6 +382,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): def test_custom_name(self): class MyFunction(GenericFunction): name = "my_func" + inherit_cache = True def __init__(self, *args): args = args + (3,) @@ -387,20 +398,24 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): package = "geo" name = "BufferOne" identifier = "buf1" + inherit_cache = True class GeoBuffer2(GenericFunction): type = Integer name = "BufferTwo" identifier = "buf2" + inherit_cache = True class BufferThree(GenericFunction): type = Integer identifier = "buf3" + inherit_cache = True class GeoBufferFour(GenericFunction): type = Integer name = "BufferFour" identifier = "Buf4" + inherit_cache = True self.assert_compile(func.geo.buf1(), "BufferOne()") self.assert_compile(func.buf2(), "BufferTwo()") @@ -413,7 +428,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): def test_custom_args(self): class myfunc(GenericFunction): - pass + inherit_cache = True self.assert_compile( myfunc(1, 2, 3), "myfunc(:myfunc_1, :myfunc_2, :myfunc_3)" @@ -1010,6 +1025,7 @@ class ExecuteTest(fixtures.TestBase): from sqlalchemy.ext.compiler import compiles class myfunc(FunctionElement): + inherit_cache = True type = Date() @compiles(myfunc) diff --git a/test/sql/test_labels.py b/test/sql/test_labels.py index 535d4dd0b..8c8e9dbed 100644 --- a/test/sql/test_labels.py +++ b/test/sql/test_labels.py @@ -805,6 +805,8 @@ class ColExprLabelTest(fixtures.TestBase, AssertsCompiledSQL): def _fixture(self): class SomeColThing(WrapsColumnExpression, ColumnElement): + inherit_cache = False + def __init__(self, expression): self.clause = coercions.expect( roles.ExpressionElementRole, expression diff --git a/test/sql/test_lambdas.py b/test/sql/test_lambdas.py index fd6b1eb41..bbf9716f5 100644 --- a/test/sql/test_lambdas.py +++ b/test/sql/test_lambdas.py @@ -17,6 +17,7 @@ from sqlalchemy.sql import roles from sqlalchemy.sql import select from sqlalchemy.sql import table from sqlalchemy.sql import util as sql_util +from sqlalchemy.sql.base import ExecutableOption from sqlalchemy.sql.traversals import HasCacheKey from sqlalchemy.testing import assert_raises_message from sqlalchemy.testing import AssertsCompiledSQL @@ -810,7 +811,10 @@ class LambdaElementTest( stmt = lambdas.lambda_stmt(lambda: select(column("x"))) - opts = {column("x"), column("y")} + class MyUncacheable(ExecutableOption): + pass + + opts = {MyUncacheable()} assert_raises_message( exc.InvalidRequestError, @@ -942,11 +946,18 @@ class LambdaElementTest( return stmt - s1 = go([column("a"), column("b")]) + class SomeOpt(HasCacheKey, ExecutableOption): + def __init__(self, x): + self.x = x + + def _gen_cache_key(self, anon_map, bindparams): + return (SomeOpt, self.x) + + s1 = go([SomeOpt("a"), SomeOpt("b")]) - s2 = go([column("a"), column("b")]) + s2 = go([SomeOpt("a"), SomeOpt("b")]) - s3 = go([column("q"), column("b")]) + s3 = go([SomeOpt("q"), SomeOpt("b")]) s1key = s1._generate_cache_key() s2key = s2._generate_cache_key() @@ -964,7 +975,7 @@ class LambdaElementTest( return stmt - class SomeOpt(HasCacheKey): + class SomeOpt(HasCacheKey, ExecutableOption): def _gen_cache_key(self, anon_map, bindparams): return ("fixed_key",) @@ -994,8 +1005,8 @@ class LambdaElementTest( return stmt - class SomeOpt(HasCacheKey): - pass + class SomeOpt(HasCacheKey, ExecutableOption): + inherit_cache = False # generates no key, will not be cached eq_(SomeOpt()._generate_cache_key(), None) diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py index 831b75e7e..6e943d236 100644 --- a/test/sql/test_operators.py +++ b/test/sql/test_operators.py @@ -656,6 +656,8 @@ class ExtensionOperatorTest(fixtures.TestBase, testing.AssertsCompiledSQL): def test_contains(self): class MyType(UserDefinedType): + cache_ok = True + class comparator_factory(UserDefinedType.Comparator): def contains(self, other, **kw): return self.op("->")(other) @@ -664,6 +666,8 @@ class ExtensionOperatorTest(fixtures.TestBase, testing.AssertsCompiledSQL): def test_getitem(self): class MyType(UserDefinedType): + cache_ok = True + class comparator_factory(UserDefinedType.Comparator): def __getitem__(self, index): return self.op("->")(index) @@ -682,6 +686,8 @@ class ExtensionOperatorTest(fixtures.TestBase, testing.AssertsCompiledSQL): def test_lshift(self): class MyType(UserDefinedType): + cache_ok = True + class comparator_factory(UserDefinedType.Comparator): def __lshift__(self, other): return self.op("->")(other) @@ -690,6 +696,8 @@ class ExtensionOperatorTest(fixtures.TestBase, testing.AssertsCompiledSQL): def test_rshift(self): class MyType(UserDefinedType): + cache_ok = True + class comparator_factory(UserDefinedType.Comparator): def __rshift__(self, other): return self.op("->")(other) diff --git a/test/sql/test_resultset.py b/test/sql/test_resultset.py index 4aa932b47..e4f07a758 100644 --- a/test/sql/test_resultset.py +++ b/test/sql/test_resultset.py @@ -1797,6 +1797,7 @@ class KeyTargetingTest(fixtures.TablesTest): def test_keyed_targeting_no_label_at_all_one(self, connection): class not_named_max(expression.ColumnElement): name = "not_named_max" + inherit_cache = True @compiles(not_named_max) def visit_max(element, compiler, **kw): @@ -1814,6 +1815,7 @@ class KeyTargetingTest(fixtures.TablesTest): def test_keyed_targeting_no_label_at_all_two(self, connection): class not_named_max(expression.ColumnElement): name = "not_named_max" + inherit_cache = True @compiles(not_named_max) def visit_max(element, compiler, **kw): diff --git a/test/sql/test_types.py b/test/sql/test_types.py index 35467de94..dc47cca46 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -1497,6 +1497,8 @@ class VariantTest(fixtures.TestBase, AssertsCompiledSQL): return process class UTypeThree(types.UserDefinedType): + cache_ok = True + def get_col_spec(self): return "UTYPETHREE" |
