Skip to content

raise NotSupportedError for Subquery, Exists, and QuerySet in annotate() #66

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ Migrations for 'admin':
- `extra()`
- `select_related()`

- `Subquery`, `Exists`, and using a `QuerySet` in `QuerySet.annotate()` aren't
supported.

- Queries with joins aren't supported.

- `DateTimeField` doesn't support microsecond precision, and correspondingly,
Expand Down
13 changes: 13 additions & 0 deletions django_mongodb/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@

from bson import Decimal128
from django.core.exceptions import EmptyResultSet, FullResultSet
from django.db import NotSupportedError
from django.db.models.expressions import (
Case,
Col,
CombinedExpression,
ExpressionWrapper,
NegatedExpression,
Subquery,
Value,
When,
)
from django.db.models.sql import Query


def case(self, compiler, connection):
Expand Down Expand Up @@ -59,6 +62,14 @@ def negated_expression(self, compiler, connection):
return {"$not": expression_wrapper(self, compiler, connection)}


def query(self, compiler, connection): # noqa: ARG001
raise NotSupportedError("Using a QuerySet in annotate() is not supported on MongoDB.")


def subquery(self, compiler, connection): # noqa: ARG001
raise NotSupportedError(f"{self.__class__.__name__} is not supported on MongoDB.")


def when(self, compiler, connection):
return self.condition.as_mql(compiler, connection)

Expand All @@ -82,5 +93,7 @@ def register_expressions():
CombinedExpression.as_mql = combined_expression
ExpressionWrapper.as_mql = expression_wrapper
NegatedExpression.as_mql = negated_expression
Query.as_mql = query
Subquery.as_mql = subquery
When.as_mql = when
Value.as_mql = value
40 changes: 22 additions & 18 deletions django_mongodb/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
# the result back to UTC.
"db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_func_with_timezone",
"db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_timezone_applied_before_truncation",
# pk__in=queryset doesn't work because subqueries aren't a thing in
# MongoDB.
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_and_alias_filter_in_subquery",
"model_fields.test_jsonfield.TestQuerying.test_usage_in_subquery",
# Length of null considered zero rather than null.
"db_functions.text.test_length.LengthTests.test_basic",
# Key transforms are incorrectly treated as joins:
Expand Down Expand Up @@ -220,25 +216,11 @@ def django_test_expected_failures(self):
"timezones.tests.NewDatabaseTests.test_query_aggregation",
},
"QuerySet.annotate() has some limitations.": {
# Exists not supported.
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_exists_none_query",
"lookup.tests.LookupTests.test_exact_exists",
"lookup.tests.LookupTests.test_nested_outerref_lhs",
"lookup.tests.LookupQueryingTests.test_filter_exists_lhs",
# annotate() with combined expressions doesn't work:
# 'WhereNode' object has no attribute 'field'
"lookup.tests.LookupQueryingTests.test_combined_annotated_lookups_in_filter",
"lookup.tests.LookupQueryingTests.test_combined_annotated_lookups_in_filter_false",
"lookup.tests.LookupQueryingTests.test_combined_lookups",
# Subquery not supported.
"annotations.tests.NonAggregateAnnotationTestCase.test_empty_queryset_annotation",
"db_functions.comparison.test_coalesce.CoalesceTests.test_empty_queryset",
"db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_outerref",
"db_functions.datetime.test_extract_trunc.DateFunctionTests.test_trunc_subquery_with_parameters",
"expressions_case.tests.CaseExpressionTests.test_in_subquery",
"lookup.tests.LookupQueryingTests.test_filter_subquery_lhs",
"model_fields.test_jsonfield.TestQuerying.test_nested_key_transform_on_subquery",
"model_fields.test_jsonfield.TestQuerying.test_obj_subquery_lookup",
# Invalid $project :: caused by :: Unknown expression $count,
"annotations.tests.NonAggregateAnnotationTestCase.test_combined_expression_annotation_with_aggregation",
"annotations.tests.NonAggregateAnnotationTestCase.test_combined_f_expression_annotation_with_aggregation",
Expand All @@ -263,6 +245,28 @@ def django_test_expected_failures(self):
# annotate().filter().count() gives incorrect results.
"db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_year_exact_lookup",
},
"Exists is not supported on MongoDB.": {
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_exists_none_query",
"lookup.tests.LookupTests.test_exact_exists",
"lookup.tests.LookupTests.test_nested_outerref_lhs",
"lookup.tests.LookupQueryingTests.test_filter_exists_lhs",
},
"Subquery is not supported on MongoDB.": {
"annotations.tests.NonAggregateAnnotationTestCase.test_empty_queryset_annotation",
"db_functions.datetime.test_extract_trunc.DateFunctionTests.test_extract_outerref",
"db_functions.datetime.test_extract_trunc.DateFunctionTests.test_trunc_subquery_with_parameters",
"lookup.tests.LookupQueryingTests.test_filter_subquery_lhs",
"model_fields.test_jsonfield.TestQuerying.test_nested_key_transform_on_subquery",
"model_fields.test_jsonfield.TestQuerying.test_obj_subquery_lookup",
},
"Using a QuerySet in annotate() is not supported on MongoDB.": {
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_and_alias_filter_in_subquery",
"annotations.tests.NonAggregateAnnotationTestCase.test_empty_expression_annotation",
"db_functions.comparison.test_coalesce.CoalesceTests.test_empty_queryset",
"expressions_case.tests.CaseExpressionTests.test_in_subquery",
"lookup.tests.LookupTests.test_in_different_database",
"model_fields.test_jsonfield.TestQuerying.test_usage_in_subquery",
},
"Count doesn't work in QuerySet.annotate()": {
"annotations.tests.AliasTests.test_alias_annotate_with_aggregation",
"annotations.tests.AliasTests.test_order_by_alias_aggregate",
Expand Down