Skip to content
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
12 changes: 12 additions & 0 deletions lib/features/mongodb/mongo_field_codec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,25 @@ import 'package:querya_desktop/features/mongodb/mongo_ejson.dart';
/// Mongo forbids `$set` of `_id` on an existing document.
bool mongoFieldIsReadOnly(String field) => field == '_id';

/// True when `$set` would treat [field] as a nested path (`a.b`), not as a
/// literal top-level key. `$set` has no escape for dots, so such a field cannot
/// be updated on its own without rewriting a different subtree.
bool mongoFieldNameIsDottedPath(String field) => field.contains('.');

/// Throws if [field] cannot be updated with `$set` on an existing document.
void mongoAssertFieldEditable(String field) {
if (mongoFieldIsReadOnly(field)) {
throw StateError(
'MongoDB forbids \$set of _id on an existing document',
);
}
if (mongoFieldNameIsDottedPath(field)) {
throw StateError(
'Field "$field" contains a dot, so a single-field update would be '
'treated as a nested path and change a different value. '
'Edit the whole document in the JSON editor instead.',
);
}
}

/// Display string for a MongoDB document field in the Cell Inspector.
Expand Down
28 changes: 28 additions & 0 deletions test/features/mongodb/mongo_field_codec_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,32 @@ void main() {
expect(() => mongoAssertFieldEditable('name'), returnsNormally);
});
});
group('dotted top-level field names', () {
test('are detected as nested paths', () {
expect(mongoFieldNameIsDottedPath('a.b'), isTrue);
expect(mongoFieldNameIsDottedPath('.a'), isTrue);
expect(mongoFieldNameIsDottedPath('name'), isFalse);
expect(mongoFieldNameIsDottedPath('a_b'), isFalse);
});

test('single-field save is refused with an explicit error', () {
expect(
() => mongoAssertFieldEditable('a.b'),
throwsA(
isA<StateError>().having(
(e) => e.message,
'message',
allOf(contains('"a.b"'), contains('JSON editor')),
),
),
);
expect(() => mongoAssertFieldEditable('ab'), returnsNormally);
});

test('dotted key is still readable in the inspector', () {
// Only Save is blocked; the dotted field itself is not read-only.
expect(mongoFieldIsReadOnly('a.b'), isFalse);
expect(mongoFieldToDisplay(1), '1');
});
});
}
Loading