From 65fa7ade129d9cdd354998575bd19ce2afeb6cba Mon Sep 17 00:00:00 2001 From: Victor Tsang Date: Fri, 29 May 2026 16:10:08 -0700 Subject: [PATCH] Added index type tests for compound Signed-off-by: Victor Tsang --- .../core/indexes/types/compound/__init__.py | 0 .../test_compound_bson_type_validation.py | 72 +++++ .../types/compound/test_compound_creation.py | 108 +++++++ .../types/compound/test_compound_errors.py | 105 ++++++ .../compound/test_compound_properties.py | 25 ++ .../types/compound/test_compound_queries.py | 298 ++++++++++++++++++ documentdb_tests/framework/error_codes.py | 1 + 7 files changed, 609 insertions(+) create mode 100644 documentdb_tests/compatibility/tests/core/indexes/types/compound/__init__.py create mode 100644 documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_bson_type_validation.py create mode 100644 documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_creation.py create mode 100644 documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_errors.py create mode 100644 documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_properties.py create mode 100644 documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_queries.py diff --git a/documentdb_tests/compatibility/tests/core/indexes/types/compound/__init__.py b/documentdb_tests/compatibility/tests/core/indexes/types/compound/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_bson_type_validation.py b/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_bson_type_validation.py new file mode 100644 index 000000000..d20632632 --- /dev/null +++ b/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_bson_type_validation.py @@ -0,0 +1,72 @@ +"""Tests for compound index key sort order BSON type validation. + +Verifies that compound index key values (sort order specifiers) reject +invalid BSON types and accept valid numeric types. +""" + +import pytest +from bson import Decimal128, Int64 + +from documentdb_tests.framework.assertions import assertFailureCode, assertNotError +from documentdb_tests.framework.bson_type_validator import ( + BsonType, + BsonTypeTestCase, + generate_bson_acceptance_test_cases, + generate_bson_rejection_test_cases, +) +from documentdb_tests.framework.error_codes import CANNOT_CREATE_INDEX_ERROR +from documentdb_tests.framework.executor import execute_command + +pytestmark = pytest.mark.index + +COMPOUND_KEY_SORT_ORDER_PARAMS = [ + BsonTypeTestCase( + id="sort_order", + msg="compound key sort order should reject non-numeric types", + keyword="sort_order", + valid_types=[BsonType.DOUBLE, BsonType.INT, BsonType.LONG, BsonType.DECIMAL], + default_error_code=CANNOT_CREATE_INDEX_ERROR, + valid_inputs={ + BsonType.DOUBLE: 1.0, + BsonType.INT: 1, + BsonType.LONG: Int64(1), + BsonType.DECIMAL: Decimal128("1"), + }, + ), +] + + +def _build_index(sample_value): + """Build a createIndexes spec with sample_value as a key sort order.""" + return {"key": {"a": sample_value, "b": 1}, "name": "test_idx"} + + +REJECTION_CASES = generate_bson_rejection_test_cases(COMPOUND_KEY_SORT_ORDER_PARAMS) + + +@pytest.mark.parametrize("bson_type,sample_value,spec", REJECTION_CASES) +def test_compound_key_sort_order_rejected(collection, bson_type, sample_value, spec): + """Test compound index creation rejects invalid BSON types for key sort order.""" + result = execute_command( + collection, + {"createIndexes": collection.name, "indexes": [_build_index(sample_value)]}, + ) + assertFailureCode(result, spec.expected_code(bson_type), msg=spec.msg) + + +ACCEPTANCE_CASES = generate_bson_acceptance_test_cases(COMPOUND_KEY_SORT_ORDER_PARAMS) + + +@pytest.mark.parametrize("bson_type,sample_value,spec", ACCEPTANCE_CASES) +def test_compound_key_sort_order_accepted(collection, bson_type, sample_value, spec): + """Test compound index creation accepts valid BSON types for key sort order. + + Note: This is a type validation test, not a functional test. We only verify + the command does not error — we do not check listIndexes to confirm the index + was created with the correct option value. + """ + result = execute_command( + collection, + {"createIndexes": collection.name, "indexes": [_build_index(sample_value)]}, + ) + assertNotError(result, msg=f"sort order should accept {bson_type.value}") diff --git a/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_creation.py b/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_creation.py new file mode 100644 index 000000000..1b332adf2 --- /dev/null +++ b/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_creation.py @@ -0,0 +1,108 @@ +"""Tests for compound index creation and idempotency. + +Validates multi-field key creation and duplicate/ordering behavior. +""" + +import pytest + +from documentdb_tests.compatibility.tests.core.indexes.commands.utils.index_test_case import ( + IndexTestCase, + index_created_response, +) +from documentdb_tests.framework.assertions import ( + assertSuccessPartial, +) +from documentdb_tests.framework.executor import execute_command +from documentdb_tests.framework.parametrize import pytest_params + +pytestmark = pytest.mark.index + +CREATION_SUCCESS_TESTS: list[IndexTestCase] = [ + IndexTestCase( + id="creation_mixed_sort_orders", + indexes=({"key": {"a": 1, "b": -1, "c": 1, "d": -1, "e": 1}, "name": "abcde"},), + msg="5-field compound with mixed sort orders succeeds", + ), + IndexTestCase( + id="creation_dot_notation", + indexes=({"key": {"a.b": 1, "a.c": 1}, "name": "ab_ac"},), + msg="Dot notation fields succeed", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(CREATION_SUCCESS_TESTS)) +def test_compound_creation_success(collection, test): + """Test compound index creation success cases.""" + result = execute_command( + collection, + {"createIndexes": collection.name, "indexes": list(test.indexes)}, + ) + assertSuccessPartial(result, index_created_response(), test.msg) + + +def test_compound_idempotent(collection): + """Test creating same compound index twice is idempotent.""" + execute_command( + collection, + { + "createIndexes": collection.name, + "indexes": [{"key": {"a": 1, "b": 1}, "name": "a_1_b_1"}], + }, + ) + result = execute_command( + collection, + { + "createIndexes": collection.name, + "indexes": [{"key": {"a": 1, "b": 1}, "name": "a_1_b_1"}], + }, + ) + assertSuccessPartial( + result, {"ok": 1.0, "numIndexesBefore": 2, "numIndexesAfter": 2}, msg="Duplicate is no-op" + ) + + +def test_compound_different_order_creates_two(collection): + """Test same fields different order creates two separate indexes.""" + execute_command( + collection, + { + "createIndexes": collection.name, + "indexes": [{"key": {"a": 1, "b": 1}, "name": "a_1_b_1"}], + }, + ) + result = execute_command( + collection, + { + "createIndexes": collection.name, + "indexes": [{"key": {"b": 1, "a": 1}, "name": "b_1_a_1"}], + }, + ) + assertSuccessPartial( + result, + {"ok": 1.0, "numIndexesBefore": 2, "numIndexesAfter": 3}, + msg="Different field order = separate index", + ) + + +def test_compound_different_sort_creates_two(collection): + """Test same fields different sort direction creates two indexes.""" + execute_command( + collection, + { + "createIndexes": collection.name, + "indexes": [{"key": {"a": 1, "b": 1}, "name": "a_1_b_1"}], + }, + ) + result = execute_command( + collection, + { + "createIndexes": collection.name, + "indexes": [{"key": {"a": 1, "b": -1}, "name": "a_1_b_neg1"}], + }, + ) + assertSuccessPartial( + result, + {"ok": 1.0, "numIndexesBefore": 2, "numIndexesAfter": 3}, + msg="Different sort = separate index", + ) diff --git a/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_errors.py b/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_errors.py new file mode 100644 index 000000000..10866e7c7 --- /dev/null +++ b/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_errors.py @@ -0,0 +1,105 @@ +"""Tests for compound index error cases. + +Validates error codes for invalid sort orders, naming conflicts, +and parallel arrays in compound indexes. +""" + +import pytest + +from documentdb_tests.compatibility.tests.core.indexes.commands.utils.index_test_case import ( + IndexTestCase, +) +from documentdb_tests.framework.assertions import assertFailureCode, assertSuccessPartial +from documentdb_tests.framework.error_codes import ( + CANNOT_CREATE_INDEX_ERROR, + CANNOT_INDEX_PARALLEL_ARRAYS_ERROR, + INDEX_KEY_SPECS_CONFLICT_ERROR, + INDEX_OPTIONS_CONFLICT_ERROR, +) +from documentdb_tests.framework.executor import execute_command +from documentdb_tests.framework.parametrize import pytest_params + +pytestmark = pytest.mark.index + +COMPOUND_CREATION_ERROR_TESTS: list[IndexTestCase] = [ + IndexTestCase( + id="sort_order_zero", + indexes=({"key": {"a": 1, "b": 0}, "name": "bad"},), + error_code=CANNOT_CREATE_INDEX_ERROR, + msg="Sort order 0 in compound should fail", + ), + IndexTestCase( + id="sort_order_null", + indexes=({"key": {"a": None, "b": 1}, "name": "bad"},), + error_code=CANNOT_CREATE_INDEX_ERROR, + msg="Sort order null in compound should fail", + ), + IndexTestCase( + id="sort_order_invalid_string", + indexes=({"key": {"a": "invalid", "b": 1}, "name": "bad"},), + error_code=CANNOT_CREATE_INDEX_ERROR, + msg="Invalid string sort order in compound should fail", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(COMPOUND_CREATION_ERROR_TESTS)) +def test_compound_creation_error(collection, test): + """Test compound index creation error cases.""" + result = execute_command( + collection, + {"createIndexes": collection.name, "indexes": list(test.indexes)}, + ) + assertFailureCode(result, test.error_code, test.msg) + + +COMPOUND_CONFLICT_ERROR_TESTS: list[IndexTestCase] = [ + IndexTestCase( + id="conflict_same_fields_different_name", + setup_indexes=[{"key": {"a": 1, "b": 1}, "name": "idx1"}], + indexes=({"key": {"a": 1, "b": 1}, "name": "idx2"},), + error_code=INDEX_OPTIONS_CONFLICT_ERROR, + msg="Same fields/order different name should fail", + ), + IndexTestCase( + id="conflict_same_name_different_fields", + setup_indexes=[{"key": {"a": 1, "b": 1}, "name": "my_idx"}], + indexes=({"key": {"c": 1, "d": 1}, "name": "my_idx"},), + error_code=INDEX_KEY_SPECS_CONFLICT_ERROR, + msg="Same name different fields should fail", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(COMPOUND_CONFLICT_ERROR_TESTS)) +def test_compound_conflict_error(collection, test): + """Test compound index naming conflict error cases.""" + execute_command( + collection, + {"createIndexes": collection.name, "indexes": list(test.setup_indexes)}, + ) + result = execute_command( + collection, + {"createIndexes": collection.name, "indexes": list(test.indexes)}, + ) + assertFailureCode(result, test.error_code, test.msg) + + +def test_compound_parallel_arrays_fail(collection): + """Test compound index with both fields as arrays fails (parallel arrays).""" + execute_command( + collection, + { + "createIndexes": collection.name, + "indexes": [{"key": {"tags": 1, "category": 1}, "name": "tags_cat"}], + }, + ) + result = execute_command( + collection, + {"insert": collection.name, "documents": [{"_id": 1, "tags": [1, 2], "category": [1, 2]}]}, + ) + assertSuccessPartial( + result, + {"writeErrors": [{"code": CANNOT_INDEX_PARALLEL_ARRAYS_ERROR}]}, + msg="Parallel arrays should fail", + ) diff --git a/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_properties.py b/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_properties.py new file mode 100644 index 000000000..9dac7a1a0 --- /dev/null +++ b/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_properties.py @@ -0,0 +1,25 @@ +"""Tests for compound index properties. + +Validates numeric equivalence in compound indexes. +""" + +import pytest +from bson import Int64 + +from documentdb_tests.framework.assertions import assertSuccess +from documentdb_tests.framework.executor import execute_command + +pytestmark = pytest.mark.index + + +def test_compound_numeric_int_query_matches_long(collection): + """Test query with int matches document with long via compound index.""" + execute_command( + collection, + {"createIndexes": collection.name, "indexes": [{"key": {"a": 1, "b": 1}, "name": "ab"}]}, + ) + collection.insert_one({"_id": 1, "a": Int64(1), "b": Int64(2)}) + result = execute_command(collection, {"find": collection.name, "filter": {"a": 1, "b": 2}}) + assertSuccess( + result, [{"_id": 1, "a": Int64(1), "b": Int64(2)}], msg="int query matches long in compound" + ) diff --git a/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_queries.py b/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_queries.py new file mode 100644 index 000000000..d715ffa86 --- /dev/null +++ b/documentdb_tests/compatibility/tests/core/indexes/types/compound/test_compound_queries.py @@ -0,0 +1,298 @@ +"""Tests for compound index query behavior. + +Validates prefix queries, sort matching, projections, hints, +nested/embedded fields, multikey, and null/missing field handling. +""" + +import pytest + +from documentdb_tests.compatibility.tests.core.indexes.commands.utils.index_test_case import ( + IndexQueryTestCase, +) +from documentdb_tests.framework.assertions import assertSuccess +from documentdb_tests.framework.executor import execute_command +from documentdb_tests.framework.parametrize import pytest_params + +pytestmark = pytest.mark.index + +_PREFIX_DOCS = ( + {"_id": 1, "a": 1, "b": 10, "c": 100}, + {"_id": 2, "a": 1, "b": 20, "c": 200}, + {"_id": 3, "a": 2, "b": 10, "c": 300}, + {"_id": 4, "a": 2, "b": 20, "c": 400}, + {"_id": 5, "a": 3, "b": 30, "c": 500}, +) + +PREFIX_QUERY_TESTS: list[IndexQueryTestCase] = [ + IndexQueryTestCase( + id="prefix_first_field", + indexes=({"key": {"a": 1, "b": -1, "c": 1}, "name": "abc"},), + doc=_PREFIX_DOCS, + filter={"a": 1}, + sort={"_id": 1}, + expected=[{"_id": 1, "a": 1, "b": 10, "c": 100}, {"_id": 2, "a": 1, "b": 20, "c": 200}], + msg="Query on prefix field a should work", + ), + IndexQueryTestCase( + id="prefix_first_two_fields", + indexes=({"key": {"a": 1, "b": -1, "c": 1}, "name": "abc"},), + doc=_PREFIX_DOCS, + filter={"a": 1, "b": 10}, + expected=[{"_id": 1, "a": 1, "b": 10, "c": 100}], + msg="Query on prefix fields a,b should work", + ), + IndexQueryTestCase( + id="prefix_all_fields", + indexes=({"key": {"a": 1, "b": -1, "c": 1}, "name": "abc"},), + doc=_PREFIX_DOCS, + filter={"a": 2, "b": 20, "c": 400}, + expected=[{"_id": 4, "a": 2, "b": 20, "c": 400}], + msg="Query on all fields should work", + ), + IndexQueryTestCase( + id="prefix_skip_first_field", + indexes=({"key": {"a": 1, "b": -1, "c": 1}, "name": "abc"},), + doc=_PREFIX_DOCS, + filter={"b": 10}, + sort={"_id": 1}, + expected=[{"_id": 1, "a": 1, "b": 10, "c": 100}, {"_id": 3, "a": 2, "b": 10, "c": 300}], + msg="Query on non-prefix field still returns correct results", + ), + IndexQueryTestCase( + id="prefix_range_on_first_field", + indexes=({"key": {"a": 1, "b": -1, "c": 1}, "name": "abc"},), + doc=_PREFIX_DOCS, + filter={"a": {"$gt": 1}, "b": 10}, + sort={"_id": 1}, + expected=[{"_id": 3, "a": 2, "b": 10, "c": 300}], + msg="Range on prefix field with equality on next field", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(PREFIX_QUERY_TESTS)) +def test_compound_prefix_query(collection, test): + """Test compound index prefix query behavior.""" + execute_command( + collection, + {"createIndexes": collection.name, "indexes": list(test.indexes)}, + ) + collection.insert_many(list(test.doc)) + cmd = {"find": collection.name, "filter": test.filter} + if test.sort: + cmd["sort"] = test.sort + result = execute_command(collection, cmd) + assertSuccess(result, test.expected, msg=test.msg) + + +_SORT_DOCS = ( + {"_id": 1, "a": 1, "b": 10}, + {"_id": 2, "a": 1, "b": 20}, + {"_id": 3, "a": 2, "b": 5}, +) + +SORT_TESTS: list[IndexQueryTestCase] = [ + IndexQueryTestCase( + id="sort_exact_match", + indexes=({"key": {"a": 1, "b": -1}, "name": "a_1_b_neg1"},), + doc=_SORT_DOCS, + filter={}, + sort={"a": 1, "b": -1}, + expected=[ + {"_id": 2, "a": 1, "b": 20}, + {"_id": 1, "a": 1, "b": 10}, + {"_id": 3, "a": 2, "b": 5}, + ], + msg="Sort matching index exactly", + ), + IndexQueryTestCase( + id="sort_reverse_match", + indexes=({"key": {"a": 1, "b": -1}, "name": "a_1_b_neg1"},), + doc=_SORT_DOCS, + filter={}, + sort={"a": -1, "b": 1}, + expected=[ + {"_id": 3, "a": 2, "b": 5}, + {"_id": 1, "a": 1, "b": 10}, + {"_id": 2, "a": 1, "b": 20}, + ], + msg="Sort matching index in reverse", + ), + IndexQueryTestCase( + id="sort_not_satisfiable_by_index", + indexes=({"key": {"a": 1, "b": 1}, "name": "a_1_b_1"},), + doc=_SORT_DOCS, + filter={}, + sort={"a": 1, "b": -1}, + expected=[ + {"_id": 2, "a": 1, "b": 20}, + {"_id": 1, "a": 1, "b": 10}, + {"_id": 3, "a": 2, "b": 5}, + ], + msg="Sort not satisfiable by index still returns correct results", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(SORT_TESTS)) +def test_compound_sort(collection, test): + """Test compound index sort order matching.""" + execute_command( + collection, + {"createIndexes": collection.name, "indexes": list(test.indexes)}, + ) + collection.insert_many(list(test.doc)) + result = execute_command( + collection, {"find": collection.name, "filter": test.filter, "sort": test.sort} + ) + assertSuccess(result, test.expected, msg=test.msg) + + +NESTED_FIELD_QUERY_TESTS: list[IndexQueryTestCase] = [ + IndexQueryTestCase( + id="embedded_fields", + indexes=({"key": {"a.x": 1, "a.y": 1}, "name": "ax_ay"},), + doc=({"_id": 1, "a": {"x": 1, "y": 10}}, {"_id": 2, "a": {"x": 2, "y": 20}}), + filter={"a.x": 1, "a.y": 10}, + expected=[{"_id": 1, "a": {"x": 1, "y": 10}}], + msg="Compound on embedded fields works", + ), + IndexQueryTestCase( + id="mixed_top_and_embedded", + indexes=({"key": {"a": 1, "b.c": 1}, "name": "a_bc"},), + doc=({"_id": 1, "a": 1, "b": {"c": 10}}, {"_id": 2, "a": 2, "b": {"c": 20}}), + filter={"a": 1, "b.c": 10}, + expected=[{"_id": 1, "a": 1, "b": {"c": 10}}], + msg="Mixed top-level and embedded works", + ), + IndexQueryTestCase( + id="multikey_one_array_field", + indexes=({"key": {"tags": 1, "category": 1}, "name": "tags_cat"},), + doc=({"_id": 1, "tags": [1, 2], "category": "a"},), + filter={"tags": 2, "category": "a"}, + expected=[{"_id": 1, "tags": [1, 2], "category": "a"}], + msg="Multikey compound query works", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(NESTED_FIELD_QUERY_TESTS)) +def test_compound_nested_field_query(collection, test): + """Test compound index nested field and multikey queries.""" + execute_command( + collection, + {"createIndexes": collection.name, "indexes": list(test.indexes)}, + ) + collection.insert_many(list(test.doc)) + result = execute_command(collection, {"find": collection.name, "filter": test.filter}) + assertSuccess(result, test.expected, msg=test.msg) + + +NULL_MISSING_QUERY_TESTS: list[IndexQueryTestCase] = [ + IndexQueryTestCase( + id="null_first_field", + indexes=({"key": {"a": 1, "b": 1}, "name": "a_1_b_1"},), + doc=({"_id": 1, "a": None, "b": 5},), + filter={"a": None, "b": 5}, + expected=[{"_id": 1, "a": None, "b": 5}], + msg="Null in first field is indexed", + ), + IndexQueryTestCase( + id="null_second_field", + indexes=({"key": {"a": 1, "b": 1}, "name": "a_1_b_1"},), + doc=({"_id": 1, "a": 5, "b": None},), + filter={"a": 5, "b": None}, + expected=[{"_id": 1, "a": 5, "b": None}], + msg="Null in second field is indexed", + ), + IndexQueryTestCase( + id="missing_first_field", + indexes=({"key": {"a": 1, "b": 1}, "name": "a_1_b_1"},), + doc=({"_id": 1, "b": 5},), + filter={"a": None}, + expected=[{"_id": 1, "b": 5}], + msg="Missing first field treated as null", + ), + IndexQueryTestCase( + id="missing_second_field", + indexes=({"key": {"a": 1, "b": 1}, "name": "a_1_b_1"},), + doc=({"_id": 1, "a": 5},), + filter={"a": 5, "b": None}, + expected=[{"_id": 1, "a": 5}], + msg="Missing second field treated as null", + ), +] + + +@pytest.mark.parametrize("test", pytest_params(NULL_MISSING_QUERY_TESTS)) +def test_compound_null_missing_query(collection, test): + """Test compound index null/missing field query behavior.""" + execute_command( + collection, + {"createIndexes": collection.name, "indexes": list(test.indexes)}, + ) + collection.insert_many(list(test.doc)) + result = execute_command(collection, {"find": collection.name, "filter": test.filter}) + assertSuccess(result, test.expected, msg=test.msg) + + +def test_compound_partial_sort_with_equality(collection): + """Test query with equality on prefix allows sort on next field.""" + execute_command( + collection, + { + "createIndexes": collection.name, + "indexes": [{"key": {"a": 1, "b": 1, "c": 1}, "name": "abc"}], + }, + ) + collection.insert_many( + [ + {"_id": 1, "a": 5, "b": 3, "c": 10}, + {"_id": 2, "a": 5, "b": 1, "c": 20}, + {"_id": 3, "a": 5, "b": 2, "c": 30}, + {"_id": 4, "a": 9, "b": 1, "c": 40}, + ] + ) + result = execute_command( + collection, {"find": collection.name, "filter": {"a": 5}, "sort": {"b": 1}} + ) + assertSuccess( + result, + [ + {"_id": 2, "a": 5, "b": 1, "c": 20}, + {"_id": 3, "a": 5, "b": 2, "c": 30}, + {"_id": 1, "a": 5, "b": 3, "c": 10}, + ], + msg="Equality on a allows sort on b", + ) + + +def test_compound_multi_field_sort_after_equality(collection): + """Test equality on prefix allows multi-field sort on remaining fields.""" + execute_command( + collection, + { + "createIndexes": collection.name, + "indexes": [{"key": {"a": 1, "b": 1, "c": 1}, "name": "abc"}], + }, + ) + collection.insert_many( + [ + {"_id": 1, "a": 5, "b": 2, "c": 30}, + {"_id": 2, "a": 5, "b": 1, "c": 20}, + {"_id": 3, "a": 5, "b": 1, "c": 10}, + {"_id": 4, "a": 9, "b": 1, "c": 5}, + ] + ) + result = execute_command( + collection, {"find": collection.name, "filter": {"a": 5}, "sort": {"b": 1, "c": 1}} + ) + assertSuccess( + result, + [ + {"_id": 3, "a": 5, "b": 1, "c": 10}, + {"_id": 2, "a": 5, "b": 1, "c": 20}, + {"_id": 1, "a": 5, "b": 2, "c": 30}, + ], + msg="Equality on a allows sort on b,c", + ) diff --git a/documentdb_tests/framework/error_codes.py b/documentdb_tests/framework/error_codes.py index 3cc8cd0af..830709328 100644 --- a/documentdb_tests/framework/error_codes.py +++ b/documentdb_tests/framework/error_codes.py @@ -34,6 +34,7 @@ COMMAND_NOT_SUPPORTED_ON_VIEW_ERROR = 166 OPTION_NOT_SUPPORTED_ON_VIEW_ERROR = 167 UNRECOGNIZED_EXPRESSION_ERROR = 168 +CANNOT_INDEX_PARALLEL_ARRAYS_ERROR = 171 QUERY_PLAN_KILLED_ERROR = 175 VIEW_PIPELINE_TOO_LARGE_ERROR = 195 INVALID_INDEX_SPEC_OPTION_ERROR = 197