Sqlalchemy 1.1 doesn't remove duplicate rows in some cases while 1.0 does
Issue #3958
resolved
After the commit next test case begun to fail:
class FilterUniqueJoinTest(fixtures.MappedTest, AssertsCompiledSQL):
run_setup_mappers = 'once'
@classmethod
def define_tables(cls, metadata):
Table('users', metadata,
Column('id', Integer, primary_key=True,
test_needs_autoincrement=True),
Column('name', String(50)),
Column('date_created', DateTime, default=datetime.datetime.now))
Table('orders', metadata,
Column('id', Integer, primary_key=True,
test_needs_autoincrement=True),
Column('user_id', Integer, ForeignKey('users.id')))
@classmethod
def setup_classes(cls):
users = cls.tables.users
orders = cls.tables.orders
class User(cls.Comparable):
pass
class Order(cls.Comparable):
pass
mapper(User, users, properties={
'orders': relationship(Order, order_by=users.c.id.desc())
})
mapper(Order, orders)
@classmethod
def insert_data(cls):
User = cls.classes.User
Order = cls.classes.Order
sess = create_session()
o1 = Order()
o2 = Order()
o3 = Order()
u1 = User(name='Mike')
u1.orders = [o1, o2]
u2 = User(name='John')
u2.orders = [o3]
sess.add(u1)
sess.add(u2)
sess.flush()
sess.close()
def test_filter_unique_column(self):
User = self.classes.User
sess = create_session()
users = (
sess.query(
User.date_created.label('dt'),
User,
)
.options(joinedload(User.orders))
.all()
)
assert len(users) == 2
def test_filter_unique_func_column(self):
User = self.classes.User
sess = create_session()
users = (
sess.query(
func.date(User.date_created, 'start of month').label('month'),
User,
)
.options(joinedload(User.orders))
.all()
)
assert len(users) == 2
Sqlalchemy 1.0:
test/orm/test_joins.py::FilterUniqueJoinTest::test_filter_unique_column PASSED
test/orm/test_joins.py::FilterUniqueJoinTest::test_filter_unique_func_column PASSED
Sqlalchemy 1.1:
test/orm/test_joins.py::FilterUniqueJoinTest::test_filter_unique_column PASSED
test/orm/test_joins.py::FilterUniqueJoinTest::test_filter_unique_func_column FAILED
Is it expected behaviour?
Comments (4)
-
repo owner -
repo owner - changed component to documentation
-
repo owner - changed status to resolved
-
reporter Thank you for quick and such detailed response.
- Log in to comment
this is expected, however the change notes could use some more examples.
First off, while I appreciate the clear test case and the effort put into it, I can't run it because I don't have time to find what specific .py file that test happens to work in, and also func.date is not a standard SQL function (and also I can't easily switch branches when the test is given as a patch). So here's the case distilled:
So here's the important part, which you'll see for yours also:
What are we seeing? 1. that func.xyz() by default returns
NullType
, because func. doesn't know what substr() or date() is. This is not new. But also 2.NullType
is not hashable. This is the change described at http://docs.sqlalchemy.org/en/rel_1_1/changelog/migration_11.html#changes-regarding-unhashable-types.If you give a type to the expression, then you're OK:
I'll try to add an example to the migration notes.