Compare commits

...

No commits in common. "c8-beta-stream-3.6" and "c8" have entirely different histories.

6 changed files with 70 additions and 335 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/SQLAlchemy-1.3.2.tar.gz SOURCES/SQLAlchemy-1.2.7.tar.gz

View File

@ -1 +1 @@
277e64612df80a1fe9c05a33f69928f5de18f5fb SOURCES/SQLAlchemy-1.3.2.tar.gz 343aa9ade5fc6b01933f5d2d8fc97c75005ac9fa SOURCES/SQLAlchemy-1.2.7.tar.gz

View File

@ -1,115 +0,0 @@
diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py
index 3077840..8719b26 100644
--- a/lib/sqlalchemy/sql/util.py
+++ b/lib/sqlalchemy/sql/util.py
@@ -20,6 +20,7 @@ from .annotation import _shallow_annotate # noqa
from .base import _from_objects
from .base import ColumnSet
from .ddl import sort_tables # noqa
+from .elements import _expand_cloned
from .elements import _find_columns # noqa
from .elements import _label_reference
from .elements import _textual_label_reference
@@ -149,6 +150,16 @@ def find_left_clause_to_join_from(clauses, join_to, onclause):
idx.append(i)
break
+ if len(idx) > 1:
+ # this is the same "hide froms" logic from
+ # Selectable._get_display_froms
+ toremove = set(
+ chain(*[_expand_cloned(f._hide_froms) for f in clauses])
+ )
+ idx = [
+ i for i in idx if clauses[i] not in toremove
+ ]
+
# onclause was given and none of them resolved, so assume
# all indexes can match
if not idx and onclause is not None:
diff --git a/test/orm/test_joins.py b/test/orm/test_joins.py
index bb9747c..4fe04f7 100644
--- a/test/orm/test_joins.py
+++ b/test/orm/test_joins.py
@@ -1559,6 +1559,81 @@ class JoinTest(QueryTest, AssertsCompiledSQL):
"ON dingalings.address_id = addresses_1.id",
)
+ def test_clause_present_in_froms_twice_w_onclause(self):
+ # test [ticket:4584]
+ Order, Address, Dingaling, User = (
+ self.classes.Order,
+ self.classes.Address,
+ self.classes.Dingaling,
+ self.classes.User,
+ )
+
+ sess = create_session()
+
+ a1 = aliased(Address)
+
+ q = sess.query(Order).select_from(Order, a1, User)
+ assert_raises_message(
+ sa.exc.InvalidRequestError,
+ "Can't determine which FROM clause to join from, there are "
+ "multiple FROMS which can join to this entity. "
+ "Try adding an explicit ON clause to help resolve the ambiguity.",
+ q.outerjoin,
+ a1,
+ )
+
+ # the condition which occurs here is: Query._from_obj contains both
+ # "a1" by itself as well as a join that "a1" is part of.
+ # find_left_clause_to_join_from() needs to include removal of froms
+ # that are in the _hide_froms of joins the same way
+ # Selectable._get_display_froms does.
+ q = sess.query(Order).select_from(Order, a1, User)
+ q = q.outerjoin(a1, a1.id == Order.address_id)
+ q = q.outerjoin(User, a1.user_id == User.id)
+
+ self.assert_compile(
+ q,
+ "SELECT orders.id AS orders_id, orders.user_id AS orders_user_id, "
+ "orders.address_id AS orders_address_id, "
+ "orders.description AS orders_description, "
+ "orders.isopen AS orders_isopen "
+ "FROM orders "
+ "LEFT OUTER JOIN addresses AS addresses_1 "
+ "ON addresses_1.id = orders.address_id "
+ "LEFT OUTER JOIN users ON addresses_1.user_id = users.id",
+ )
+
+ def test_clause_present_in_froms_twice_wo_onclause(self):
+ # test [ticket:4584]
+ Order, Address, Dingaling, User = (
+ self.classes.Order,
+ self.classes.Address,
+ self.classes.Dingaling,
+ self.classes.User,
+ )
+
+ sess = create_session()
+
+ a1 = aliased(Address)
+
+ # the condition which occurs here is: Query._from_obj contains both
+ # "a1" by itself as well as a join that "a1" is part of.
+ # find_left_clause_to_join_from() needs to include removal of froms
+ # that are in the _hide_froms of joins the same way
+ # Selectable._get_display_froms does.
+ q = sess.query(User).select_from(Dingaling, a1, User)
+ q = q.outerjoin(a1, User.id == a1.user_id)
+ q = q.outerjoin(Dingaling)
+
+ self.assert_compile(
+ q,
+ "SELECT users.id AS users_id, users.name AS users_name "
+ "FROM users LEFT OUTER JOIN addresses AS addresses_1 "
+ "ON users.id = addresses_1.user_id "
+ "LEFT OUTER JOIN dingalings "
+ "ON addresses_1.id = dingalings.address_id",
+ )
+
def test_multiple_adaption(self):
Item, Order, User = (
self.classes.Item,

View File

@ -0,0 +1,28 @@
From 3fd3ac6d554019f54efe1935f3a25cb5939fdad3 Mon Sep 17 00:00:00 2001
From: Nils Philippsen <nils@tiptoe.de>
Date: Mon, 18 Jun 2018 00:08:38 +0200
Subject: [PATCH] fix TypeReflectionTest for sqlite 3.24
SQLite 3.24 added support for PostgreSQL-style UPSERT. This added two
new keywords 'DO' and 'NOTHING' which made
test_round_trip_direct_type_affinity() fail with a syntax error.
---
test/dialect/test_sqlite.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/dialect/test_sqlite.py b/test/dialect/test_sqlite.py
index 4c462aed1..d2d563208 100644
--- a/test/dialect/test_sqlite.py
+++ b/test/dialect/test_sqlite.py
@@ -1637,7 +1637,7 @@ class TypeReflectionTest(fixtures.TestBase):
("BLOBBER", sqltypes.NullType()),
("DOUBLE PRECISION", sqltypes.REAL()),
("FLOATY", sqltypes.REAL()),
- ("NOTHING WE KNOW", sqltypes.NUMERIC()),
+ ("SOMETHING UNKNOWN", sqltypes.NUMERIC()),
]
def _fixture_as_string(self, fixture):
--
2.17.1

View File

@ -1,142 +0,0 @@
From 6d1f6b7dce58bfd112d662486956f919f1640f4f Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Thu, 7 Dec 2023 11:44:37 +0100
Subject: [PATCH] Include GROUP BY in _should_nest_selectable criteria
Fixed bug where usage of joined eager loading would not properly wrap the
query inside of a subquery when :meth:`.Query.group_by` were used against
the query. When any kind of result-limiting approach is used, such as
DISTINCT, LIMIT, OFFSET, joined eager loading embeds the row-limited query
inside of a subquery so that the collection results are not impacted. For
some reason, the presence of GROUP BY was never included in this criterion,
even though it has a similar effect as using DISTINCT. Additionally, the
bug would prevent using GROUP BY at all for a joined eager load query for
most database platforms which forbid non-aggregated, non-grouped columns
from being in the query, as the additional columns for the joined eager
load would not be accepted by the database.
Fixes: #5065
Change-Id: I9a2ed8196f83297ec38012138d1a5acdf9e88155
(cherry picked from commit 2d5fa22)
---
lib/sqlalchemy/orm/query.py | 1 +
test/orm/test_eager_relations.py | 40 +++++++++++++++++++++++++++++
test/orm/test_subquery_relations.py | 39 ++++++++++++++++++++++++++++
3 files changed, 80 insertions(+)
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index 9544b7d..321b14d 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -3479,6 +3479,7 @@ class Query(object):
kwargs.get("limit") is not None
or kwargs.get("offset") is not None
or kwargs.get("distinct", False)
+ or kwargs.get("group_by", False)
)
def exists(self):
diff --git a/test/orm/test_eager_relations.py b/test/orm/test_eager_relations.py
index 4adf9a7..5a1d4f4 100644
--- a/test/orm/test_eager_relations.py
+++ b/test/orm/test_eager_relations.py
@@ -1109,6 +1109,46 @@ class EagerTest(_fixtures.FixtureTest, testing.AssertsCompiledSQL):
self.assert_sql_count(testing.db, go, 1)
+ def test_group_by_only(self):
+ # like distinct(), a group_by() has a similar effect so the
+ # joined eager load needs to subquery for this as well
+ users, Address, addresses, User = (
+ self.tables.users,
+ self.classes.Address,
+ self.tables.addresses,
+ self.classes.User,
+ )
+
+ mapper(
+ User,
+ users,
+ properties={
+ "addresses": relationship(
+ mapper(Address, addresses),
+ lazy="joined",
+ order_by=addresses.c.email_address,
+ )
+ },
+ )
+
+ q = create_session().query(User)
+ eq_(
+ [
+ User(id=7, addresses=[Address(id=1)]),
+ User(
+ id=8,
+ addresses=[
+ Address(id=3, email_address="ed@bettyboop.com"),
+ Address(id=4, email_address="ed@lala.com"),
+ Address(id=2, email_address="ed@wood.com"),
+ ],
+ ),
+ User(id=9, addresses=[Address(id=5)]),
+ User(id=10, addresses=[]),
+ ],
+ q.order_by(User.id).group_by(User).all(), # group by all columns
+ )
+
def test_limit_2(self):
keywords, items, item_keywords, Keyword, Item = (
self.tables.keywords,
diff --git a/test/orm/test_subquery_relations.py b/test/orm/test_subquery_relations.py
index 117ab5b..ce44061 100644
--- a/test/orm/test_subquery_relations.py
+++ b/test/orm/test_subquery_relations.py
@@ -1112,6 +1112,45 @@ class EagerTest(_fixtures.FixtureTest, testing.AssertsCompiledSQL):
result = q.order_by(sa.desc(User.id)).limit(2).offset(2).all()
eq_(list(reversed(self.static.user_all_result[0:2])), result)
+ def test_group_by_only(self):
+ # test group_by() not impacting results, similarly to joinedload
+ users, Address, addresses, User = (
+ self.tables.users,
+ self.classes.Address,
+ self.tables.addresses,
+ self.classes.User,
+ )
+
+ mapper(
+ User,
+ users,
+ properties={
+ "addresses": relationship(
+ mapper(Address, addresses),
+ lazy="subquery",
+ order_by=addresses.c.email_address,
+ )
+ },
+ )
+
+ q = create_session().query(User)
+ eq_(
+ [
+ User(id=7, addresses=[Address(id=1)]),
+ User(
+ id=8,
+ addresses=[
+ Address(id=3, email_address="ed@bettyboop.com"),
+ Address(id=4, email_address="ed@lala.com"),
+ Address(id=2, email_address="ed@wood.com"),
+ ],
+ ),
+ User(id=9, addresses=[Address(id=5)]),
+ User(id=10, addresses=[]),
+ ],
+ q.order_by(User.id).group_by(User).all(), # group by all columns
+ )
+
def test_one_to_many_scalar(self):
Address, addresses, users, User = (
self.classes.Address,
--
2.43.0

View File

@ -1,20 +1,18 @@
%global debug_package %{nil}
%if 0%{?fedora} || 0%{?rhel} > 7 %if 0%{?fedora} || 0%{?rhel} > 7
%bcond_without python3 %global with_python3 1
%endif %endif
# python2X and python3X are built form the same module, so we need a conditional for python2 bits %if 0%{?rhel} > 7
# the state of the conditional is not important in the spec, it is set in modulemd # Disable python2 build by default
%bcond_with python2 %bcond_with python2
%else
%bcond_without python2
%bcond_with python36_module %endif
%global srcname SQLAlchemy %global srcname SQLAlchemy
Name: python-sqlalchemy Name: python-sqlalchemy
Version: 1.3.2 Version: 1.2.7
Release: 3%{?dist} Release: 3%{?dist}
Summary: Modular and flexible ORM library for python Summary: Modular and flexible ORM library for python
@ -23,16 +21,9 @@ License: MIT
URL: http://www.sqlalchemy.org/ URL: http://www.sqlalchemy.org/
Source0: https://files.pythonhosted.org/packages/source/S/%{srcname}/%{srcname}-%{version}.tar.gz Source0: https://files.pythonhosted.org/packages/source/S/%{srcname}/%{srcname}-%{version}.tar.gz
# Fold entities into existing joins when resolving FROM ambiguity. # Fix tests for sqlite 3.24
# This regression was introduced with the 1.3 sqlalchemy series. # https://github.com/zzzeek/sqlalchemy/pull/452
# Fixed upstream: https://github.com/sqlalchemy/sqlalchemy/commit/25a42e93f4ef5ce1a9f9c23fbcdea3e21a7b3f1a Patch1: python-sqlalchemy-1.2.8-sqlite-3.24.patch
# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1829932
Patch0: fix-regression-in-ambiguous-join-logic.patch
# Include GROUP BY in _should_nest_selectable criteria
# Upstream issue: https://github.com/sqlalchemy/sqlalchemy/issues/5065
# Backported from upstream change: https://github.com/sqlalchemy/sqlalchemy/commit/2d5fa22c7d53ff8109d47ba5ae4fe3b9849ddd09
Patch1: sqlalchemy-1.4.0-group_by_joined_relations.patch
BuildRequires: gcc BuildRequires: gcc
@ -41,15 +32,10 @@ BuildRequires: python2-devel >= 2.6
BuildRequires: python2-setuptools BuildRequires: python2-setuptools
BuildRequires: python2-mock BuildRequires: python2-mock
BuildRequires: python2-pytest BuildRequires: python2-pytest
%endif %endif # with python2
%if %{with python3} %if 0%{?with_python3}
%if %{with python36_module}
BuildRequires: python36-devel
BuildRequires: python36-rpm-macros
%else
BuildRequires: python3-devel BuildRequires: python3-devel
%endif
BuildRequires: python3-setuptools BuildRequires: python3-setuptools
BuildRequires: python3-pytest BuildRequires: python3-pytest
%endif %endif
@ -63,8 +49,6 @@ as you choose, determining relationships based on foreign keys or letting you
define the join conditions explicitly, to bridge the gap between database and define the join conditions explicitly, to bridge the gap between database and
domain. domain.
This package includes the python 2 version of the module.
%package doc %package doc
Summary: Documentation for SQLAlchemy Summary: Documentation for SQLAlchemy
BuildArch: noarch BuildArch: noarch
@ -88,9 +72,9 @@ define the join conditions explicitly, to bridge the gap between database and
domain. domain.
This package includes the python 2 version of the module. This package includes the python 2 version of the module.
%endif %endif # with python2
%if %{with python3} %if 0%{?with_python3}
%package -n python3-sqlalchemy %package -n python3-sqlalchemy
Summary: Modular and flexible ORM library for python Summary: Modular and flexible ORM library for python
Group: Development/Libraries Group: Development/Libraries
@ -106,24 +90,31 @@ define the join conditions explicitly, to bridge the gap between database and
domain. domain.
This package includes the python 3 version of the module. This package includes the python 3 version of the module.
%endif # with python3 %endif # with_python3
# Filter unnecessary dependencies
%global __provides_exclude_from ^(%{python2_sitearch}|%{python3_sitearch})/.*\\.so$
%prep %prep
%setup -n %{srcname}-%{version} %setup -q -n %{srcname}-%{version}
%patch0 -p1
%patch1 -p1 %patch1 -p1 -b .sqlite-3.24
%build %build
%{?with_python2:%py2_build} %if %{with python2}
%py2_build
%endif # with python2
%if %{with python3} %if 0%{?with_python3}
%py3_build %py3_build
%endif %endif
%install %install
%{?with_python2:%py2_install} %if %{with python2}
%py2_install
%endif # with python2
%if %{with python3} %if 0%{?with_python3}
%py3_install %py3_install
%endif %endif
@ -131,9 +122,11 @@ This package includes the python 3 version of the module.
rm -rf doc/build rm -rf doc/build
%check %check
%{?with_python2:PYTHONPATH=. %{__python2} -m pytest test} %if %{with python2}
PYTHONPATH=. %{__python2} -m pytest test
%endif # with python2
%if %{with python3} %if 0%{?with_python3}
PYTHONPATH=. %{__python3} -m pytest test PYTHONPATH=. %{__python3} -m pytest test
%endif %endif
@ -146,50 +139,21 @@ PYTHONPATH=. %{__python3} -m pytest test
%license LICENSE %license LICENSE
%doc README.rst %doc README.rst
%{python2_sitearch}/* %{python2_sitearch}/*
%endif %endif # with python2
%if %{with python3} %if 0%{?with_python3}
%files -n python3-sqlalchemy %files -n python3-sqlalchemy
%license LICENSE %license LICENSE
%doc README.rst %doc README.rst
%{python3_sitearch}/* %{python3_sitearch}/*
%endif # with python3 %endif # with_python3
%changelog %changelog
* Mon Dec 04 2023 Lumír Balhar <lbalhar@redhat.com> - 1.3.2-3 * Wed Aug 01 2018 Petr Viktorin <pviktori@redhat.com> - 1.2.7-3
- Fix GROUP BY for joined relationships - Fix tests with SQLite 3.24+
Resolves: RHEL-17464
* Fri May 15 2020 Charalampos Stratakis <cstratak@redhat.com> - 1.3.2-2 * Thu Jun 14 2018 Charalampos Stratakis <cstratak@redhat.com> - 1.2.7-2
- Fix regression in ambiguous join logic - Conditionalize the python2 subpackage
Resolves: rhbz#1829932
* Fri Apr 05 2019 Charalampos Stratakis <cstratak@redhat.com> - 1.3.2-1
- Rebase to 1.3.2 to fix CVE-2019-7164 and CVE-2019-7548
Resolves: rhbz#1695754
* Tue Jul 31 2018 Lumír Balhar <lbalhar@redhat.com> - 1.2.8-6
- Switch python3 coditions to bcond
* Wed Jul 18 2018 Tomas Orsava <torsava@redhat.com> - 1.2.8-5
- BuildRequire also python36-rpm-macros as part of the python36 module build
* Wed Jul 04 2018 Miro Hrončok <mhroncok@redhat.com> - 1.2.8-4
- Add a bcond for python2
- Remove provides filter, it was only needed 100 years ago
* Sun Jun 17 2018 Nils Philippsen <nils@tiptoe.de> - 1.2.8-3
- rename patch, apply with backups
- fix failing test for sqlite 3.24 instead of skipping it
* Thu Jun 14 2018 Miro Hrončok <mhroncok@redhat.com> - 1.2.8-2
- Rebuilt for Python 3.7
* Tue Jun 05 2018 Nils Philippsen <nils@tiptoe.de> - 1.2.8-1
- version 1.2.8
* Mon Apr 30 2018 Tomas Orsava <torsava@redhat.com> - 1.2.7-2
- Require the python36-devel package when building for the python36 module
* Sun Apr 22 2018 Nils Philippsen <nils@tiptoe.de> - 1.2.7-1 * Sun Apr 22 2018 Nils Philippsen <nils@tiptoe.de> - 1.2.7-1
- version 1.2.7 - version 1.2.7