@@ -456,7 +456,7 @@ void testCreateOrReplaceAndReturn(String storeName) throws Exception {
456456 }
457457
458458 @ Nested
459- class SubDocCompatibilityTest {
459+ class SubdocUpdateConsistencyTests {
460460
461461 @ Nested
462462 @ DisplayName ("SET Operator Tests" )
@@ -523,6 +523,29 @@ void testSetTopLevelArray(String storeName) throws Exception {
523523 assertEquals ("tag6" , tagsNode .get (2 ).asText ());
524524 }
525525
526+ @ ParameterizedTest (name = "{0}: SET top-level array" )
527+ @ ArgumentsSource (AllStoresProvider .class )
528+ void testSetTopLevelEmptyArray (String storeName ) throws Exception {
529+ String docId = generateDocId ("set-array" );
530+ insertTestDocument (docId );
531+
532+ Collection collection = getCollection (storeName );
533+ Query query = buildQueryById (docId );
534+
535+ List <SubDocumentUpdate > updates = List .of (SubDocumentUpdate .of ("tags" , new String [] {}));
536+
537+ UpdateOptions options =
538+ UpdateOptions .builder ().returnDocumentType (ReturnDocumentType .AFTER_UPDATE ).build ();
539+
540+ Optional <Document > result = collection .update (query , updates , options );
541+
542+ assertTrue (result .isPresent ());
543+ JsonNode resultJson = OBJECT_MAPPER .readTree (result .get ().toJson ());
544+ JsonNode tagsNode = resultJson .get ("tags" );
545+ assertTrue (tagsNode .isArray ());
546+ assertEquals (0 , tagsNode .size (), storeName );
547+ }
548+
526549 @ ParameterizedTest (name = "{0}: SET nested JSONB primitive" )
527550 @ ArgumentsSource (AllStoresProvider .class )
528551 void testSetNestedJsonbPrimitive (String storeName ) throws Exception {
@@ -931,6 +954,90 @@ void testAddToListIfAbsentOnNonArrayField(String storeName) throws Exception {
931954 }
932955 }
933956
957+ @ Nested
958+ class AllOperatorTests {
959+
960+ @ ParameterizedTest
961+ @ ArgumentsSource (AllStoresProvider .class )
962+ void testMultipleUpdatesOnSameFieldThrowsException (String storeName ) throws IOException {
963+ String docId = generateDocId ("multiple-updates-on-same-field" );
964+ insertTestDocument (docId );
965+
966+ Collection collection = getCollection (storeName );
967+ Query query = buildQueryById (docId );
968+
969+ // top-level primitives
970+ List <SubDocumentUpdate > topLevelPrimitiveUpdates =
971+ List .of (
972+ SubDocumentUpdate .builder ()
973+ .subDocument ("price" )
974+ .operator (UpdateOperator .ADD )
975+ .subDocumentValue (SubDocumentValue .of (5 ))
976+ .build (),
977+ SubDocumentUpdate .builder ()
978+ .subDocument ("price" )
979+ .operator (UpdateOperator .ADD )
980+ .subDocumentValue (SubDocumentValue .of (-15 ))
981+ .build ());
982+
983+ UpdateOptions options =
984+ UpdateOptions .builder ().returnDocumentType (ReturnDocumentType .AFTER_UPDATE ).build ();
985+
986+ // Since there are multiple updates on the same field, it should throw an exception
987+ assertThrows (
988+ Exception .class , () -> collection .update (query , topLevelPrimitiveUpdates , options ));
989+
990+ // top-level arrays
991+ List <SubDocumentUpdate > topLevelArrayUpdates =
992+ List .of (
993+ SubDocumentUpdate .builder ()
994+ .subDocument ("tags" )
995+ .operator (UpdateOperator .APPEND_TO_LIST )
996+ .subDocumentValue (SubDocumentValue .of (new String [] {"tag1" , "tag2" }))
997+ .build (),
998+ SubDocumentUpdate .builder ()
999+ .subDocument ("tags" )
1000+ .operator (UpdateOperator .REMOVE_ALL_FROM_LIST )
1001+ .subDocumentValue (SubDocumentValue .of (new String [] {"tag2" }))
1002+ .build ());
1003+
1004+ assertThrows (
1005+ Exception .class , () -> collection .update (query , topLevelArrayUpdates , options ));
1006+
1007+ // nested array updates
1008+ List <SubDocumentUpdate > nestedArrayUpdates =
1009+ List .of (
1010+ SubDocumentUpdate .builder ()
1011+ .subDocument ("sales.regions" )
1012+ .operator (UpdateOperator .SET )
1013+ .subDocumentValue (SubDocumentValue .of (new String [] {"US" , "EU" , "APAC" }))
1014+ .build (),
1015+ SubDocumentUpdate .builder ()
1016+ .subDocument ("sales.regions" )
1017+ .operator (UpdateOperator .ADD_TO_LIST_IF_ABSENT )
1018+ .subDocumentValue (SubDocumentValue .of (new String [] {"EMEA" }))
1019+ .build ());
1020+
1021+ assertThrows (Exception .class , () -> collection .update (query , nestedArrayUpdates , options ));
1022+
1023+ // nested primitives
1024+ List <SubDocumentUpdate > nestedPrimitiveUpdates =
1025+ List .of (
1026+ SubDocumentUpdate .builder ()
1027+ .subDocument ("props.brand" )
1028+ .operator (UpdateOperator .SET )
1029+ .subDocumentValue (SubDocumentValue .of ("NewBrand" ))
1030+ .build (),
1031+ SubDocumentUpdate .builder ()
1032+ .subDocument ("props.brand" )
1033+ .operator (UpdateOperator .ADD_TO_LIST_IF_ABSENT )
1034+ .subDocumentValue (SubDocumentValue .of ("NewBrand2" ))
1035+ .build ());
1036+
1037+ assertThrows (Exception .class , () -> collection .update (query , nestedArrayUpdates , options ));
1038+ }
1039+ }
1040+
9341041 @ Nested
9351042 @ DisplayName ("REMOVE_ALL_FROM_LIST Operator Tests" )
9361043 class RemoveAllFromListOperatorTests {
0 commit comments