Exemplo n.º 1
0
 def test_expressions(self):
     self.assertEqual(
         repr(Case(When(a=1))),
         "<Case: CASE WHEN <Q: (AND: ('a', 1))> THEN Value(None), ELSE Value(None)>"
     )
     self.assertEqual(repr(Col('alias', 'field')), "Col(alias, field)")
     self.assertEqual(repr(Date('published', 'exact')),
                      "Date(published, exact)")
     self.assertEqual(repr(DateTime('published', 'exact', utc)),
                      "DateTime(published, exact, %s)" % utc)
     self.assertEqual(repr(F('published')), "F(published)")
     self.assertEqual(repr(F('cost') + F('tax')),
                      "<CombinedExpression: F(cost) + F(tax)>")
     self.assertEqual(
         repr(ExpressionWrapper(
             F('cost') + F('tax'), models.IntegerField())),
         "ExpressionWrapper(F(cost) + F(tax))")
     self.assertEqual(repr(Func('published', function='TO_CHAR')),
                      "Func(F(published), function=TO_CHAR)")
     self.assertEqual(repr(OrderBy(Value(1))),
                      'OrderBy(Value(1), descending=False)')
     self.assertEqual(repr(Random()), "Random()")
     self.assertEqual(repr(RawSQL('table.col', [])),
                      "RawSQL(table.col, [])")
     self.assertEqual(repr(Ref('sum_cost', Sum('cost'))),
                      "Ref(sum_cost, Sum(F(cost)))")
     self.assertEqual(repr(Value(1)), "Value(1)")
Exemplo n.º 2
0
class TestRandom(WrapperTestBase):
    model_class = WrapperStubModel
    factory = WrapperStubFactory
    expression = Random()

    def test_expression_evaluates_to_expected(self, mocker):
        expected = 0.56
        mocker.patch('dj_hybrid.expression_wrapper.wrappers.random.random',
                     return_value=expected)
        model_instance = self.get_populated_model()
        python_outcome = self.get_as_python(model_instance)
        assert python_outcome == expected

    def test_parity_with_database(self):
        # we can't actually test parity, however we can check the return types
        model_instance = self.get_populated_model()
        python_outcome = self.get_as_python(model_instance)
        database_outcome = self.get_from_database(model_instance)

        assert type(python_outcome) is type(database_outcome)

    def test_cached_per_instance(self):
        instance_1 = self.factory()
        instance_2 = self.factory()
        wrapped = self.get_wrapped()

        assert wrapped.as_python(instance_1) is wrapped.as_python(instance_1)
        assert wrapped.as_python(instance_2) is wrapped.as_python(instance_2)
        assert wrapped.as_python(instance_1) is not wrapped.as_python(
            instance_2)
Exemplo n.º 3
0
 def get_queryset(self, request):
     return super().get_queryset(request).prefetch_related(
         'discounts',
         'payments',
     ).select_related(
         'subject',
         'user',
     ).annotate(random_number=Random())
Exemplo n.º 4
0
 def handle(self, *args, **options):
     count = options.get('count')
     depth = options.get('depth')
     if count / depth < 10:
         raise Exception(
             'The count should be at least 10 times larger than the depth')
     self.stdout.write('Run  "%s"...' % __name__.split('.')[-1])
     if options.get('cleanup'):
         self.stdout.write('Cleanup database')
         User.objects.all().delete()
         Post.objects.all().delete()
         Comment.objects.all().delete()
     users = [UserFactory() for _ in range(10)]
     entities = users + [PostFactory() for _ in range(10)]
     roots_count = options.get('roots_count', int(count // depth // 2))
     self.stdout.write('Create tree')
     with tqdm(total=roots_count * depth) as pbar:
         for root_idx in range(roots_count):
             parent = None
             for depth_idx in range(depth):
                 parent = CommentFactory.create(
                     parent=parent,
                     user=random.choice(users),
                     entity=random.choice(entities))
                 pbar.update()
     remain_count = count - roots_count * depth
     remain_comments = []
     self.stdout.write('Create remains')
     with tqdm(total=remain_count) as pbar:
         for random_comment in range(remain_count):
             remain_comments.append(
                 CommentFactory.build(parent=Comment.objects.annotate(
                     random=Random()).order_by('random').first(),
                                      user=random.choice(users)))
             pbar.update()
         Comment.objects.bulk_create(remain_comments, batch_size=100)
Exemplo n.º 5
0
def get_order_by(self):
    """
    See original get_group_by at django.db.models.sql.compiler>SQLCompiler
    """
    if self.query.extra_order_by:
        ordering = self.query.extra_order_by
    elif not self.query.default_ordering:
        ordering = self.query.order_by
    else:
        ordering = (self.query.order_by or self.query.get_meta().ordering
                    or [])
    if self.query.standard_ordering:
        asc, desc = ORDER_DIR['ASC']
    else:
        asc, desc = ORDER_DIR['DESC']

    order_by = []
    for field in ordering:
        if hasattr(field, 'resolve_expression'):
            if not isinstance(field, OrderBy):
                field = field.asc()
            if not self.query.standard_ordering:
                field.reverse_ordering()
            order_by.append((field, False))
            continue
        if field == '?':  # random
            order_by.append((OrderBy(Random()), False))
            continue

        col, order = get_order_dir(field, asc)
        descending = True if order == 'DESC' else False

        if col in self.query.annotation_select:
            # Reference to expression in SELECT clause
            order_by.append((OrderBy(Ref(col,
                                         self.query.annotation_select[col]),
                                     descending=descending), True))
            continue
        if col in self.query.annotations:
            # References to an expression which is masked out of the SELECT clause
            order_by.append((OrderBy(self.query.annotations[col],
                                     descending=descending), False))
            continue

        if '.' in field:
            # This came in through an extra(order_by=...) addition. Pass it
            # on verbatim.
            table, col = col.split('.', 1)
            order_by.append((OrderBy(RawSQL(
                '%s.%s' % (self.quote_name_unless_alias(table), col), []),
                                     descending=descending), False))
            continue

        if not self.query._extra or col not in self.query._extra:
            # 'col' is of the form 'field' or 'field1__field2' or
            # '-field1__field2__field', etc.
            order_by.extend(
                self.find_ordering_name(field,
                                        self.query.get_meta(),
                                        default_order=asc))
        else:
            if col not in self.query.extra_select:
                order_by.append((OrderBy(RawSQL(*self.query.extra[col]),
                                         descending=descending), False))
            else:
                order_by.append((OrderBy(Ref(col,
                                             RawSQL(*self.query.extra[col])),
                                         descending=descending), True))
    result = []
    # changed from set() to []
    seen = []

    for expr, is_ref in order_by:
        if self.query.combinator:
            src = expr.get_source_expressions()[0]
            # Relabel order by columns to raw numbers if this is a combined
            # query; necessary since the columns can't be referenced by the
            # fully qualified name and the simple column names may collide.
            for idx, (sel_expr, _, col_alias) in enumerate(self.select):
                if is_ref and col_alias == src.refs:
                    src = src.source
                elif col_alias:
                    continue
                if src == sel_expr:
                    expr.set_source_expressions([RawSQL('%d' % (idx + 1), ())])
                    break
            else:
                raise DatabaseError(
                    'ORDER BY term does not match any column in the result set.'
                )
        resolved = expr.resolve_expression(self.query,
                                           allow_joins=True,
                                           reuse=None)
        sql, params = self.compile(resolved)
        # Don't add the same column twice, but the order direction is
        # not taken into account so we strip it. When this entire method
        # is refactored into expressions, then we can check each part as we
        # generate it.
        without_ordering = self.ordering_parts.search(sql).group(1)
        if (without_ordering, tuple(params)) in seen:
            continue
        # changed from add to append
        seen.append((without_ordering, tuple(params)))
        result.append((resolved, (sql, params, is_ref)))
    return result
Exemplo n.º 6
0
    def get_order_by(self):
        """
        Returns a list of 2-tuples of form (expr, (sql, params)) for the
        ORDER BY clause.

        The order_by clause can alter the select clause (for example it
        can add aliases to clauses that do not yet have one, or it can
        add totally new select clauses).
        """
        if self.query.extra_order_by:
            ordering = self.query.extra_order_by
        elif not self.query.default_ordering:
            ordering = self.query.order_by
        else:
            ordering = (self.query.order_by or self.query.get_meta().ordering
                        or [])
        if self.query.standard_ordering:
            asc, desc = ORDER_DIR['ASC']
        else:
            asc, desc = ORDER_DIR['DESC']

        order_by = []
        for pos, field in enumerate(ordering):
            if hasattr(field, 'resolve_expression'):
                if not isinstance(field, OrderBy):
                    field = field.asc()
                if not self.query.standard_ordering:
                    field.reverse_ordering()
                order_by.append((field, False))
                continue
            if field == '?':  # random
                order_by.append((OrderBy(Random()), False))
                continue

            col, order = get_order_dir(field, asc)
            descending = True if order == 'DESC' else False

            if col in self.query.annotation_select:
                order_by.append(
                    (OrderBy(Ref(col, self.query.annotation_select[col]),
                             descending=descending), True))
                continue

            if '.' in field:
                # This came in through an extra(order_by=...) addition. Pass it
                # on verbatim.
                table, col = col.split('.', 1)
                order_by.append((OrderBy(RawSQL(
                    '%s.%s' % (self.quote_name_unless_alias(table), col), []),
                                         descending=descending), False))
                continue

            if not self.query._extra or col not in self.query._extra:
                # 'col' is of the form 'field' or 'field1__field2' or
                # '-field1__field2__field', etc.
                order_by.extend(
                    self.find_ordering_name(field,
                                            self.query.get_meta(),
                                            default_order=asc))
            else:
                if col not in self.query.extra_select:
                    order_by.append((OrderBy(RawSQL(*self.query.extra[col]),
                                             descending=descending), False))
                else:
                    order_by.append(
                        (OrderBy(Ref(col, RawSQL(*self.query.extra[col])),
                                 descending=descending), True))
        result = []
        seen = set()

        for expr, is_ref in order_by:
            resolved = expr.resolve_expression(self.query,
                                               allow_joins=True,
                                               reuse=None)
            sql, params = self.compile(resolved)
            # Don't add the same column twice, but the order direction is
            # not taken into account so we strip it. When this entire method
            # is refactored into expressions, then we can check each part as we
            # generate it.
            without_ordering = self.ordering_parts.search(sql).group(1)
            if (without_ordering, tuple(params)) in seen:
                continue
            seen.add((without_ordering, tuple(params)))
            result.append((resolved, (sql, params, is_ref)))
        return result
Exemplo n.º 7
0
    def get_order_by(self):
        """
        Return a list of 2-tuples of form (expr, (sql, params, is_ref)) for the
        ORDER BY clause.

        The order_by clause can alter the select clause (for example it
        can add aliases to clauses that do not yet have one, or it can
        add totally new select clauses).
        """
        if self.query.extra_order_by:
            ordering = self.query.extra_order_by
        elif not self.query.default_ordering:
            ordering = self.query.order_by
        elif self.query.order_by:
            ordering = self.query.order_by
        elif self.query.get_meta().ordering:
            ordering = self.query.get_meta().ordering
            self._meta_ordering = ordering
        else:
            ordering = []
        if self.query.standard_ordering:
            asc, desc = ORDER_DIR['ASC']
        else:
            asc, desc = ORDER_DIR['DESC']

        order_by = []
        for field in ordering:
            if hasattr(field, 'resolve_expression'):
                if isinstance(field, Value):
                    # output_field must be resolved for constants.
                    field = Cast(field, field.output_field)
                if not isinstance(field, OrderBy):
                    field = field.asc()
                if not self.query.standard_ordering:
                    field = field.copy()
                    field.reverse_ordering()
                    order_by.append((field, True))
                else:
                    order_by.append((field, False))
                continue
            if field == '?':  # random
                order_by.append((OrderBy(Random()), False))
                continue

            col, order = get_order_dir(field, asc)
            descending = order == 'DESC'

            if col in self.query.annotation_select:
                # Reference to expression in SELECT clause
                order_by.append((
                    OrderBy(Ref(col, self.query.annotation_select[col]), descending=descending),
                    True))
                continue
            if col in self.query.annotations:
                # References to an expression which is masked out of the SELECT
                # clause.
                expr = self.query.annotations[col]
                if isinstance(expr, Value):
                    # output_field must be resolved for constants.
                    expr = Cast(expr, expr.output_field)
                order_by.append((OrderBy(expr, descending=descending), False))
                continue            

            if '.' in field:
                # This came in through an extra(order_by=...) addition. Pass it
                # on verbatim.
                table, col = col.split('.', 1)
                order_by.append((
                    OrderBy(
                        RawSQL('%s.%s' % (self.quote_name_unless_alias(table), col), []),
                        descending=descending
                    ), False))
                continue

            if not self.query.extra or col not in self.query.extra:
                # 'col' is of the form 'field' or 'field1__field2' or
                # '-field1__field2__field', etc.
                order_by.extend(self.find_ordering_name(
                    field, self.query.get_meta(), default_order=asc))
            else:
                if col not in self.query.extra_select:
                    order_by.append((
                        OrderBy(RawSQL(*self.query.extra[col]), descending=descending),
                        False))
                else:
                    order_by.append((
                        OrderBy(Ref(col, RawSQL(*self.query.extra[col])), descending=descending),
                        True))
        result = []
        seen = set()

        for expr, is_ref in order_by:
            resolved = expr.resolve_expression(self.query, allow_joins=True, reuse=None)
            if self.query.combinator:
                src = resolved.get_source_expressions()[0]
                expr_src = expr.get_source_expressions()[0]
                # Relabel order by columns to raw numbers if this is a combined
                # query; necessary since the columns can't be referenced by the
                # fully qualified name and the simple column names may collide.
                for idx, (sel_expr, _, col_alias) in enumerate(self.select):
                    if is_ref and col_alias == src.refs:
                        src = src.source
                    elif col_alias and not (
                        isinstance(expr_src, F) and col_alias == expr_src.name
                    ):
                        continue
                    if src == sel_expr:
                        resolved.set_source_expressions([RawSQL('%d' % (idx + 1), ())])
                        break
                else:
                    if col_alias:
                        raise DatabaseError('ORDER BY term does not match any column in the result set.')
                    # Add column used in ORDER BY clause without an alias to
                    # the selected columns.
                    self.query.add_select_col(src)
                    resolved.set_source_expressions([RawSQL('%d' % len(self.query.select), ())])
            sql, params = self.compile(resolved)            
            # Don't add the same column twice, but the order direction is
            # not taken into account so we strip it. When this entire method
            # is refactored into expressions, then we can check each part as we
            # generate it.
            without_ordering = self.ordering_parts.search(sql)[1]
            params_hash = make_hashable(params)
            if (without_ordering, params_hash) in seen:
                continue
            seen.add((without_ordering, params_hash))
            result.append((resolved, (sql, params, is_ref)))
        return result
Exemplo n.º 8
0
 def get_order_by(self):
     result = super().get_order_by()
     result.append((OrderBy(Random()), ('RANDOM()', [], False)))
     return result