@@ -1098,7 +1098,7 @@ TEST(List_UpdateIfNeeded)
1098
1098
auto table = tr->add_table (" table" );
1099
1099
auto col = table->add_column (type_Mixed, " mixed" );
1100
1100
auto col2 = table->add_column (type_Mixed, " col2" );
1101
- table->create_object ();
1101
+ auto leading_obj = table->create_object ();
1102
1102
Obj obj = table->create_object ();
1103
1103
obj.set_collection (col, CollectionType::List);
1104
1104
@@ -1123,9 +1123,24 @@ TEST(List_UpdateIfNeeded)
1123
1123
// The list is now non-empty, so a new accessor can initialize
1124
1124
auto list_3 = obj.get_list <Mixed>(col);
1125
1125
CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::Updated);
1126
+ CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::NoChange);
1127
+
1128
+ // A copy of a list is lazily initialized, so it's updated on first call
1129
+ // even if the source was up-to-date
1130
+ auto list_4 = std::make_shared<Lst<Mixed>>(list_3);
1131
+ CHECK_EQUAL (list_4->update_if_needed (), UpdateStatus::Updated);
1132
+
1133
+ // Nested lists work the same way as top-level ones
1134
+ list_4->insert_collection (1 , CollectionType::List);
1135
+ auto list_4_1 = list_4->get_list (1 );
1136
+ auto list_4_2 = list_4->get_list (1 );
1137
+ list_4_1->add (Mixed ());
1138
+ // FIXME: this should be NoChange
1139
+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::Updated);
1140
+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::Updated);
1126
1141
1127
1142
// Update the row index of the parent object, forcing it to update
1128
- table-> remove_object (table-> begin () );
1143
+ leading_obj. remove ( );
1129
1144
1130
1145
// Updating the base object directly first doesn't change the result of
1131
1146
// updating the list
@@ -1135,6 +1150,12 @@ TEST(List_UpdateIfNeeded)
1135
1150
CHECK_EQUAL (list_2.update_if_needed (), UpdateStatus::Updated);
1136
1151
CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::Updated);
1137
1152
1153
+ // These two lists share the same parent, so the first updates due to the
1154
+ // parent returning Updated, and the second updates due to seeing that the
1155
+ // parent version has changed
1156
+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::Updated);
1157
+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::Updated);
1158
+
1138
1159
tr->commit_and_continue_as_read ();
1139
1160
1140
1161
// Committing the write transaction changes the obj's ref, so everything
@@ -1143,6 +1164,8 @@ TEST(List_UpdateIfNeeded)
1143
1164
CHECK_EQUAL (list_1.update_if_needed (), UpdateStatus::Updated);
1144
1165
CHECK_EQUAL (list_2.update_if_needed (), UpdateStatus::Updated);
1145
1166
CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::Updated);
1167
+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::Updated);
1168
+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::Updated);
1146
1169
1147
1170
// Perform a write which does not result in obj changing
1148
1171
{
@@ -1157,6 +1180,8 @@ TEST(List_UpdateIfNeeded)
1157
1180
CHECK_EQUAL (list_1.update_if_needed (), UpdateStatus::NoChange);
1158
1181
CHECK_EQUAL (list_2.update_if_needed (), UpdateStatus::NoChange);
1159
1182
CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::NoChange);
1183
+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::NoChange);
1184
+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::NoChange);
1160
1185
1161
1186
// Perform a write which does modify obj
1162
1187
{
@@ -1171,6 +1196,8 @@ TEST(List_UpdateIfNeeded)
1171
1196
CHECK_EQUAL (list_1.update_if_needed (), UpdateStatus::Updated);
1172
1197
CHECK_EQUAL (list_2.update_if_needed (), UpdateStatus::Updated);
1173
1198
CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::Updated);
1199
+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::Updated);
1200
+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::Updated);
1174
1201
1175
1202
// Everything updates to detached when the object is removed
1176
1203
tr->promote_to_write ();
@@ -1180,4 +1207,41 @@ TEST(List_UpdateIfNeeded)
1180
1207
CHECK_EQUAL (list_1.update_if_needed (), UpdateStatus::Detached);
1181
1208
CHECK_EQUAL (list_2.update_if_needed (), UpdateStatus::Detached);
1182
1209
CHECK_EQUAL (list_3.update_if_needed (), UpdateStatus::Detached);
1210
+ CHECK_EQUAL (list_4_1->update_if_needed (), UpdateStatus::Detached);
1211
+ CHECK_EQUAL (list_4_2->update_if_needed (), UpdateStatus::Detached);
1212
+ }
1213
+
1214
+ TEST (List_AsCollectionParent)
1215
+ {
1216
+ Group g;
1217
+ auto table = g.add_table (" table" );
1218
+ auto col = table->add_column (type_Mixed, " mixed" );
1219
+
1220
+ Obj obj = table->create_object ();
1221
+ obj.set_collection (col, CollectionType::List);
1222
+ auto list_1 = obj.get_list <Mixed>(col);
1223
+ list_1.insert_collection (0 , CollectionType::List);
1224
+
1225
+ // list_1 is stack allocated, so we have to create a new object which can
1226
+ // serve as the owner. This object is not reused for multiple calls.
1227
+ auto list_1_1 = list_1.get_list (0 );
1228
+ auto list_1_2 = list_1.get_list (0 );
1229
+ CHECK_NOT_EQUAL (list_1_1->get_owner (), &list_1);
1230
+ CHECK_NOT_EQUAL (list_1_1->get_owner (), list_1_2->get_owner ());
1231
+
1232
+ // list_2 is heap allocated but not owned by a shared_ptr, so we have to
1233
+ // create a new object which can serve as the owner. This object is not
1234
+ // reused for multiple calls.
1235
+ auto list_2 = obj.get_list_ptr <Mixed>(col);
1236
+ auto list_2_1 = list_2->get_list (0 );
1237
+ auto list_2_2 = list_2->get_list (0 );
1238
+ CHECK_NOT_EQUAL (list_2_1->get_owner (), list_2.get ());
1239
+ CHECK_NOT_EQUAL (list_2_1->get_owner (), list_2_2->get_owner ());
1240
+
1241
+ // list_3 is owned by a shared_ptr, so we can just use it as the owner directly
1242
+ auto list_3 = std::shared_ptr{std::move (list_2)};
1243
+ auto list_3_1 = list_3->get_list (0 );
1244
+ auto list_3_2 = list_3->get_list (0 );
1245
+ CHECK_EQUAL (list_3_1->get_owner (), list_3.get ());
1246
+ CHECK_EQUAL (list_3_1->get_owner (), list_3_2->get_owner ());
1183
1247
}
0 commit comments