~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/bugs/model/bugtask.py

  • Committer: Launchpad Patch Queue Manager
  • Date: 2012-01-04 16:19:40 UTC
  • mfrom: (14616.2.2 bug-909318)
  • Revision ID: launchpad@pqm.canonical.com-20120104161940-wxc81swjnsofjakb
[r=gmb][bug=909318] bug fix: invalid SQL query when a bugtask search
 consisting of a UNION of two or more sub-.queries is ordered by a value that
 requires to join another table.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2368
2368
                "BugTask.datecreated > %s" % (
2369
2369
                    sqlvalues(params.created_since,)))
2370
2370
 
2371
 
        orderby_arg, extra_joins = self._processOrderBy(params)
2372
 
        join_tables.extend(extra_joins)
2373
 
 
2374
2371
        query = " AND ".join(extra_clauses)
2375
2372
 
2376
2373
        if not decorators:
2386
2383
        else:
2387
2384
            with_clause = None
2388
2385
        return (
2389
 
            query, clauseTables, orderby_arg, decorator, join_tables,
 
2386
            query, clauseTables, decorator, join_tables,
2390
2387
            has_duplicate_results, with_clause)
2391
2388
 
2392
2389
    def buildUpstreamClause(self, params):
2644
2641
                    SpecificationBug.specification %s)
2645
2642
                """ % search_value_to_where_condition(linked_blueprints)
2646
2643
 
2647
 
    def buildOrigin(self, join_tables, prejoin_tables, clauseTables):
 
2644
    def buildOrigin(self, join_tables, prejoin_tables, clauseTables,
 
2645
                    start_with=BugTask):
2648
2646
        """Build the parameter list for Store.using().
2649
2647
 
2650
2648
        :param join_tables: A sequence of tables that should be joined
2663
2661
        and in clauseTables. This method ensures that each table
2664
2662
        appears exactly once in the returned sequence.
2665
2663
        """
2666
 
        origin = [BugTask]
 
2664
        origin = [start_with]
2667
2665
        already_joined = set(origin)
2668
2666
        for table, join in join_tables:
2669
2667
            if table is None or table not in already_joined:
2691
2689
        :param args: optional additional BugTaskSearchParams instances,
2692
2690
        """
2693
2691
        orig_store = store = IStore(BugTask)
2694
 
        [query, clauseTables, orderby, bugtask_decorator, join_tables,
 
2692
        [query, clauseTables, bugtask_decorator, join_tables,
2695
2693
        has_duplicate_results, with_clause] = self.buildQuery(params)
2696
2694
        if with_clause:
2697
2695
            store = store.with_(with_clause)
 
2696
        orderby_expression, orderby_joins = self._processOrderBy(params)
2698
2697
        if len(args) == 0:
2699
2698
            if has_duplicate_results:
2700
2699
                origin = self.buildOrigin(join_tables, [], clauseTables)
2701
 
                outer_origin = self.buildOrigin([], prejoins, [])
 
2700
                outer_origin = self.buildOrigin(
 
2701
                     orderby_joins, prejoins, [])
2702
2702
                subquery = Select(BugTask.id, where=SQL(query), tables=origin)
2703
2703
                resultset = store.using(*outer_origin).find(
2704
2704
                    resultrow, In(BugTask.id, subquery))
2705
2705
            else:
2706
 
                origin = self.buildOrigin(join_tables, prejoins, clauseTables)
 
2706
                origin = self.buildOrigin(
 
2707
                    join_tables + orderby_joins, prejoins, clauseTables)
2707
2708
                resultset = store.using(*origin).find(resultrow, query)
2708
2709
            if prejoins:
2709
2710
                decorator = lambda row: bugtask_decorator(row[0])
2710
2711
            else:
2711
2712
                decorator = bugtask_decorator
2712
2713
 
2713
 
            resultset.order_by(orderby)
 
2714
            resultset.order_by(orderby_expression)
2714
2715
            return DecoratedResultSet(resultset, result_decorator=decorator,
2715
2716
                pre_iter_hook=pre_iter_hook)
2716
2717
 
2720
2721
 
2721
2722
        decorators = [bugtask_decorator]
2722
2723
        for arg in args:
2723
 
            [query, clauseTables, ignore, decorator, join_tables,
 
2724
            [query, clauseTables, decorator, join_tables,
2724
2725
             has_duplicate_results, with_clause] = self.buildQuery(arg)
2725
2726
            origin = self.buildOrigin(join_tables, [], clauseTables)
2726
2727
            localstore = store
2745
2746
                bugtask = decorator(bugtask)
2746
2747
            return bugtask
2747
2748
 
2748
 
        origin = [Alias(resultset._get_select(), "BugTask")]
 
2749
        origin = self.buildOrigin(
 
2750
            orderby_joins, prejoins, [],
 
2751
            start_with=Alias(resultset._get_select(), "BugTask"))
2749
2752
        if prejoins:
2750
 
            origin += [join for table, join in prejoins]
2751
2753
            decorator = prejoin_decorator
2752
2754
        else:
2753
2755
            decorator = simple_decorator
2754
2756
 
2755
2757
        result = store.using(*origin).find(resultrow)
2756
 
        result.order_by(orderby)
 
2758
        result.order_by(orderby_expression)
2757
2759
        return DecoratedResultSet(result, result_decorator=decorator,
2758
2760
            pre_iter_hook=pre_iter_hook)
2759
2761