mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-15 13:17:24 -04:00
22f65156bb
Replace :meth:`_orm.Query.with_labels` and :meth:`_sql.GenerativeSelect.apply_labels` with explicit getters and setters ``get_label_style`` and ``set_label_style`` to accommodate the three supported label styles: ``LABEL_STYLE_DISAMBIGUATE_ONLY`` (default), ``LABEL_STYLE_TABLENAME_PLUS_COL``, and ``LABEL_STYLE_NONE``. In addition, for Core and "future style" ORM queries, ``LABEL_STYLE_DISAMBIGUATE_ONLY`` is now the default label style. This style differs from the existing "no labels" style in that labeling is applied in the case of column name conflicts; with ``LABEL_STYLE_NONE``, a duplicate column name is not accessible via name in any case. For legacy ORM queries using :class:`_query.Query`, the table-plus-column names labeling style applied by ``LABEL_STYLE_TABLENAME_PLUS_COL`` continues to be used so that existing test suites and logging facilities see no change in behavior by default, however this style of labeling is no longer required for SQLAlchemy queries to function, as result sets are commonly matched to columns using a positional approach since SQLAlchemy 1.0. Within test suites, all use of apply_labels() / use_labels now uses the new methods. New tests added to test/sql/test_deprecations.py nad test/orm/test_deprecations.py to cover just the old apply_labels() method call. Tests in ORM that made explicit use apply_labels()/ etc. where it isn't needed for the ORM to work correctly use default label style now. Co-authored-by: Mike Bayer <mike_mp@zzzcomputing.com> Fixes: #4757 Change-Id: I5fdcd2ed4ae8c7fe62f8be2b6d0e8f66409b6a54
108 lines
3.0 KiB
Python
108 lines
3.0 KiB
Python
from sqlalchemy import Column
|
|
from sqlalchemy import Integer
|
|
from sqlalchemy import MetaData
|
|
from sqlalchemy import select
|
|
from sqlalchemy import String
|
|
from sqlalchemy import Table
|
|
from sqlalchemy.engine import default
|
|
from sqlalchemy.sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL
|
|
from sqlalchemy.testing import AssertsExecutionResults
|
|
from sqlalchemy.testing import fixtures
|
|
from sqlalchemy.testing import profiling
|
|
|
|
|
|
t1 = t2 = None
|
|
|
|
|
|
class CompileTest(fixtures.TestBase, AssertsExecutionResults):
|
|
__requires__ = ("cpython",)
|
|
__backend__ = True
|
|
|
|
@classmethod
|
|
def setup_test_class(cls):
|
|
|
|
global t1, t2, metadata
|
|
metadata = MetaData()
|
|
t1 = Table(
|
|
"t1",
|
|
metadata,
|
|
Column("c1", Integer, primary_key=True),
|
|
Column("c2", String(30)),
|
|
)
|
|
|
|
t2 = Table(
|
|
"t2",
|
|
metadata,
|
|
Column("c1", Integer, primary_key=True),
|
|
Column("c2", String(30)),
|
|
)
|
|
|
|
cls.dialect = default.DefaultDialect()
|
|
|
|
# do a "compile" ahead of time to load
|
|
# deferred imports, use the dialect to pre-load
|
|
# dialect-level types
|
|
t1.insert().compile(dialect=cls.dialect)
|
|
|
|
# go through all the TypeEngine
|
|
# objects in use and pre-load their _type_affinity
|
|
# entries.
|
|
for t in (t1, t2):
|
|
for c in t.c:
|
|
c.type._type_affinity
|
|
from sqlalchemy.sql import sqltypes
|
|
|
|
for t in list(sqltypes._type_map.values()):
|
|
t._type_affinity
|
|
|
|
@profiling.function_call_count()
|
|
def test_insert(self):
|
|
t1.insert().compile(dialect=self.dialect)
|
|
|
|
@profiling.function_call_count(variance=0.15)
|
|
def test_update(self):
|
|
t1.update().compile(dialect=self.dialect)
|
|
|
|
def test_update_whereclause(self):
|
|
t1.update().where(t1.c.c2 == 12).compile(dialect=self.dialect)
|
|
|
|
@profiling.function_call_count()
|
|
def go():
|
|
t1.update().where(t1.c.c2 == 12).compile(dialect=self.dialect)
|
|
|
|
go()
|
|
|
|
def test_select(self):
|
|
# give some of the cached type values
|
|
# a chance to warm up
|
|
s = select(t1).where(t1.c.c2 == t2.c.c1)
|
|
s.compile(dialect=self.dialect)
|
|
|
|
@profiling.function_call_count(variance=0.15, warmup=1)
|
|
def go():
|
|
s = select(t1).where(t1.c.c2 == t2.c.c1)
|
|
s.compile(dialect=self.dialect)
|
|
|
|
go()
|
|
|
|
def test_select_labels(self):
|
|
# give some of the cached type values
|
|
# a chance to warm up
|
|
s = (
|
|
select(t1)
|
|
.where(t1.c.c2 == t2.c.c1)
|
|
.set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL)
|
|
)
|
|
s.compile(dialect=self.dialect)
|
|
|
|
@profiling.function_call_count(variance=0.15, warmup=1)
|
|
def go():
|
|
s = (
|
|
select(t1)
|
|
.where(t1.c.c2 == t2.c.c1)
|
|
.set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL)
|
|
)
|
|
s.compile(dialect=self.dialect)
|
|
|
|
go()
|