Browse Source

Make pagure work with recent sqlalchemy versions

Fixes https://pagure.io/pagure/issue/4415

Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
Pierre-Yves Chibon 5 years ago
parent
commit
df9b15c896
2 changed files with 23 additions and 16 deletions
  1. 22 11
      pagure/lib/query.py
  2. 1 5
      requirements.txt

+ 22 - 11
pagure/lib/query.py

@@ -2439,7 +2439,7 @@ def search_projects(
                 model.User.user == private,
             )
         )
-        sub_q2 = session.query(model.Project.id).filter(
+        sub_q2 = session.query(sqlalchemy.distinct(model.Project.id)).filter(
             # User got admin or commit right
             sqlalchemy.and_(
                 model.Project.private == True,  # noqa: E712
@@ -2452,7 +2452,7 @@ def search_projects(
                 ),
             )
         )
-        sub_q3 = session.query(model.Project.id).filter(
+        sub_q3 = session.query(sqlalchemy.distinct(model.Project.id)).filter(
             # User created a group that has admin or commit right
             sqlalchemy.and_(
                 model.Project.private == True,  # noqa: E712
@@ -2467,7 +2467,7 @@ def search_projects(
                 ),
             )
         )
-        sub_q4 = session.query(model.Project.id).filter(
+        sub_q4 = session.query(sqlalchemy.distinct(model.Project.id)).filter(
             # User is part of a group that has admin or commit right
             sqlalchemy.and_(
                 model.Project.private == True,  # noqa: E712
@@ -2494,14 +2494,25 @@ def search_projects(
                 model.PagureGroup.group_name.notin_(exclude_groups)
             )
 
-        projects = projects.filter(
-            model.Project.id.in_(
-                subquery0.union(sub_q1)
-                .union(sub_q2)
-                .union(sub_q3)
-                .union(sub_q4)
+        private_repo_subq = (
+            subquery0.union(sub_q1).union(sub_q2).union(sub_q3).union(sub_q4)
+        )
+
+        # There is something going on here, we shouldn't have to invoke/call
+        # the sub-query, it should work fine with:
+        #    model.Project.id.in_(private_repo_subq.subquery())
+        # however, it does not. Either something gets really confused with
+        # sqlite or the generated SQL is broken
+        # The issues seems to be with the unions in the subquery just above.
+        # Since we can't quite get this to work, let's bite the bullet and go
+        # with this approach, but damn I don't like it!
+        # This issue appeared with sqlalchemy 1.3.0 and is still present in
+        # 1.3.13 tested today.
+        private_repos = private_repo_subq.all()
+        if private_repos:
+            projects = projects.filter(
+                model.Project.id.in_(list(set(zip(*private_repos)))[0])
             )
-        )
 
     if fork is not None:
         if fork is True:
@@ -2532,7 +2543,7 @@ def search_projects(
         projects = projects.filter(model.Project.namespace == namespace)
 
     query = session.query(model.Project).filter(
-        model.Project.id.in_(projects.subquery())
+        model.Project.id.in_(projects.as_scalar())
     )
 
     if sort == "latest":

+ 1 - 5
requirements.txt

@@ -27,11 +27,7 @@ redis
 requests
 six
 # sqlalchemy minimum 0.8
-# sqlalchemy 1.3.0 is causing issues on the pip container leading
-# test_pagure_lib.py to raise a:
-# "(sqlite3.OperationalError) no such column: users.user"
-# in test_search_projects_private line 319
-sqlalchemy < 1.3.0
+sqlalchemy >= 0.8
 # 1.4.0 is broken, 1.4.0-post-1 works but gives odd results on newer setuptools
 # the latest version 1.5.0 is also known to work
 straight.plugin