コード例 #1
0
ファイル: q.py プロジェクト: nextfit/tortoise-orm
    def _resolve_filter(self, queryset: "AwaitableStatement[MODEL]", context: QueryContext, key, value) -> QueryClauses:
        context_item = context.top
        model = context_item.model
        table = context_item.table

        if value is None and "isnull" in model._meta.db.filter_class.FILTER_FUNC_MAP:
            value = True
            key = f"{key}{LOOKUP_SEP}isnull"

        relation_field_name, _, field_sub = key.partition(LOOKUP_SEP)
        if self._check_annotations and relation_field_name in queryset.annotations:
            (filter_operator, _) = model._meta.db.filter_class.FILTER_FUNC_MAP[field_sub]
            annotation = queryset.annotations[relation_field_name]
            if annotation.field.is_aggregate:
                return QueryClauses(having_criterion=filter_operator(annotation.field, value))
            else:
                return QueryClauses(where_criterion=filter_operator(annotation.field, value))

        field_object = model._meta.fields_map.get(relation_field_name)
        if not field_object:
            raise UnknownFieldError(relation_field_name, model)

        key_filter = model._meta.get_filter(key)
        if key_filter:
            if isinstance(field_object, RelationField):
                join_data = context.join_table_by_field(table, field_object, full=False)
                if join_data:
                    #
                    # We are potentially adding two None here into the context
                    # however, since we have a valid key_filter it means no sub_field
                    # and hence to inner tables and no context is necessary, except
                    # for the correct position of the stack levels,
                    #
                    context.push(join_data.model, join_data.table)
                    clauses = QueryClauses(where_criterion=key_filter(context, value))
                    context.pop()
                else:
                    clauses = QueryClauses(where_criterion=key_filter(context, value))

                return clauses

            else:
                return QueryClauses(where_criterion=key_filter(context, value))

        if isinstance(field_object, RelationField):
            join_data = context.join_table_by_field(table, field_object)
            context.push(join_data.model, join_data.table)

            q = Q(**{field_sub: value})
            q._check_annotations = False
            modifier = q._resolve(queryset=queryset, context=context)
            context.pop()

            return modifier

        raise BaseFieldError(key, model)
コード例 #2
0
ファイル: annotations.py プロジェクト: nextfit/tortoise-orm
    def resolve_into(self, queryset: "AwaitableStatement[MODEL]",
                     context: QueryContext):
        self._field_object, self._field = context.resolve_term(
            self._term, queryset, accept_relation=True)

        model = context.top.model
        table = context.top.table
        if self._add_group_by and self._field.is_aggregate:
            context.query = context.query.groupby(
                table[model._meta.pk_db_column])
コード例 #3
0
    def resolve_into(self, queryset: "AwaitableQuery[MODEL]",
                     context: QueryContext):
        # So far as I can imagine, the annotation will be expanded
        # independently, we just refer to it here.
        _, field = context.resolve_field_name(self.field_name,
                                              queryset,
                                              accept_relation=False,
                                              expand_annotation=False)

        if not queryset.is_aggregate() or context.query._groupbys:
            context.query = context.query.orderby(field, order=self.direction)
コード例 #4
0
    def resolve_into(self, queryset: "AwaitableQuery[MODEL]",
                     context: QueryContext):
        if isinstance(self.node, Term):
            term_annotation = TermAnnotation(self.node)
            term_annotation.resolve_into(queryset, context)

            field = term_annotation.field
            direction = Order.asc
            if isinstance(field, Negative):
                field = field.term
                direction = Order.desc

            context.query = context.query.orderby(field, order=direction)

        else:
            context.query = context.query.orderby(self.node)
コード例 #5
0
    def test_q_with_blank_or3(self):
        q = Q() | Q(id__gt=5)
        r = q._resolve(
            TestQCall.DummyQuerySet(),
            QueryContext(QueryBuilder()).push(CharFields, CharFields._meta.table())
        )

        self.assertEqual(r.where_criterion.get_sql(), '"id">5')
コード例 #6
0
    def test_q_complex_int3(self):
        q = Q(Q(id__lt=5, id__gt=50, join_type="OR"), join_type="AND", intnum=80)
        r = q._resolve(
            TestQCall.DummyQuerySet(),
            QueryContext(QueryBuilder()).push(IntFields, IntFields._meta.table())
        )

        self.assertEqual(r.where_criterion.get_sql(), '"intnum"=80 AND ("id"<5 OR "id">50)')
コード例 #7
0
    def test_q_multiple_or2(self):
        q = Q(join_type="OR", id=8, intnum=80)
        r = q._resolve(
            TestQCall.DummyQuerySet(),
            QueryContext(QueryBuilder()).push(IntFields, IntFields._meta.table())
        )

        self.assertEqual(r.where_criterion.get_sql(), '"id"=8 OR "intnum"=80')
コード例 #8
0
    def test_q_multiple_and(self):
        q = Q(join_type="AND", id__gt=8, id__lt=10)
        r = q._resolve(
            TestQCall.DummyQuerySet(),
            QueryContext(QueryBuilder()).push(IntFields, IntFields._meta.table())
        )

        self.assertEqual(r.where_criterion.get_sql(), '"id">8 AND "id"<10')
コード例 #9
0
    def test_q_basic_or(self):
        q = Q(join_type="OR", id=8)
        r = q._resolve(
            TestQCall.DummyQuerySet(),
            QueryContext(QueryBuilder()).push(IntFields, IntFields._meta.table())
        )

        self.assertEqual(r.where_criterion.get_sql(), '"id"=8')
コード例 #10
0
ファイル: queryset.py プロジェクト: nextfit/tortoise-orm
    def create_query_context(self, parent_context: Optional[QueryContext]) -> QueryContext:
        query = self.query_builder(parent_context.alias if parent_context else None)\
            .select(*self.model._meta.db_columns)

        context = QueryContext(query, parent_context)
        context.push(self.model, query._from[-1])
        context.resolve_select_related(self._select_related)
        context.pop()

        return context
コード例 #11
0
    def test_q_complex_char3(self):
        q = Q(~Q(char__lt=5, char__gt=50, join_type="OR"), join_type="AND", char_null=80)
        r = q._resolve(
            TestQCall.DummyQuerySet(),
            QueryContext(QueryBuilder()).push(CharFields, CharFields._meta.table())
        )

        self.assertEqual(
            r.where_criterion.get_sql(),
            "\"char_null\"='80' AND NOT (\"char\"<'5' OR \"char\">'50')",
        )
コード例 #12
0
ファイル: statements.py プロジェクト: nextfit/tortoise-orm
    def create_query(self, parent_context: Optional[QueryContext]) -> QueryBuilder:
        query = self.query_builder(parent_context.alias if parent_context else None)
        context = QueryContext(query, parent_context)
        context.push(self.model, query._from[-1])
        self._add_query_details(context=context)
        context.query._delete_from = True
        context.pop()

        return context.query
コード例 #13
0
ファイル: statements.py プロジェクト: nextfit/tortoise-orm
    def create_query(self, parent_context: Optional[QueryContext]) -> QueryBuilder:

        db_client = self._get_db_client()
        table = self.model._meta.table(parent_context.alias if parent_context else None)

        context = QueryContext(query=db_client.query_class.update(table), parent_context=parent_context)
        context.push(self.model, table)
        self._add_query_details(context=context)

        for field_name, value in self.update_kwargs.items():
            field_object = self.model._meta.fields_map.get(field_name)

            if not field_object:
                raise UnknownFieldError(field_name, self.model)

            if field_object.primary_key:
                raise IntegrityError(f"Field {field_name} is primary key and can not be updated")

            if isinstance(field_object, RelationField):
                if isinstance(field_object, (ForeignKey, OneToOneField)):
                    fk_field_name: str = field_object.id_field_name
                    fk_field_object = self.model._meta.fields_map[fk_field_name]
                    value = fk_field_object.db_value(value.pk, None)
                    context.query = context.query.set(fk_field_object.db_column, value)

                else:
                    raise NotADbColumnFieldError(field_name, self.model)

            else:
                if isinstance(value, Term):
                    value = TermAnnotation(value)
                    value.resolve_into(self, context)
                    value = value.field

                elif isinstance(value, Annotation):
                    value.resolve_into(self, context)
                    value = value.field

                else:
                    value = field_object.db_value(value, None)

                context.query = context.query.set(field_object.db_column, value)

        context.pop()
        return context.query
コード例 #14
0
ファイル: fieldselect.py プロジェクト: nextfit/tortoise-orm
    def create_query(self, parent_context: QueryContext) -> QueryBuilder:
        query = self.query_builder(
            parent_context.alias if parent_context else None)
        context = QueryContext(query, parent_context)
        context.push(self.model, query._from[-1])

        self._add_query_details(context=context)
        for return_as, field_name in self.fields_for_select.items():
            _, field = context.resolve_field_name(field_name,
                                                  self,
                                                  accept_relation=False)
            context.query._select_other(field.as_(return_as))

        context.pop()
        return context.query