Skip to content

Commit 988e50b

Browse files
committed
Add the restriction of _id modification in mysqlx.DbDoc.
This patch adds the restriction of _id modification in mysqlx.DbDoc. The new method copy() returns a new copy of a mysqlx.DbDoc object containing the doc_id provided. If doc_id is not provided, it will be removed from the new mysqlx.DbDoc object. A new test was created for mysqlx.DbDoc.
1 parent c3396ea commit 988e50b

File tree

3 files changed

+66
-2
lines changed

3 files changed

+66
-2
lines changed

lib/mysqlx/crud.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,7 @@ def add_or_replace_one(self, doc_id, doc):
400400
"""
401401
if not isinstance(doc, DbDoc):
402402
doc = DbDoc(doc)
403-
doc["_id"] = doc_id
404-
return self.add(doc).upsert(True).execute()
403+
return self.add(doc.copy(doc_id)).upsert(True).execute()
405404

406405
def get_one(self, doc_id):
407406
"""Returns a Document matching the Document ID.

lib/mysqlx/dbdoc.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,35 @@ def __init__(self, value):
5454
def __str__(self):
5555
return json.dumps(self.__dict__)
5656

57+
def __repr__(self):
58+
return repr(self.__dict__)
59+
5760
def __setitem__(self, index, value):
61+
if index == "_id":
62+
raise ProgrammingError("Cannot modify _id")
5863
self.__dict__[index] = value
5964

6065
def __getitem__(self, index):
6166
return self.__dict__[index]
6267

68+
def copy(self, doc_id=None):
69+
"""Returns a new copy of a :class:`mysqlx.DbDoc` object containing the
70+
`doc_id` provided. If `doc_id` is not provided, it will be removed from
71+
new :class:`mysqlx.DbDoc` object.
72+
73+
Args:
74+
doc_id (Optional[str]): Document ID
75+
76+
Returns:
77+
mysqlx.DbDoc: A new instance of DbDoc containing the _id provided
78+
"""
79+
new_dict = self.__dict__.copy()
80+
if doc_id:
81+
new_dict["_id"] = doc_id
82+
elif "_id" in new_dict:
83+
del new_dict["_id"]
84+
return DbDoc(new_dict)
85+
6386
def keys(self):
6487
"""Returns the keys.
6588

tests/test_mysqlx_crud.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,48 @@ def drop_view(schema, view_name):
6868
schema.get_session().sql(query).execute()
6969

7070

71+
@unittest.skipIf(tests.MYSQL_VERSION < (5, 7, 12), "XPlugin not compatible")
72+
class MySQLxDbDocTests(tests.MySQLxTests):
73+
74+
def setUp(self):
75+
self.connect_kwargs = tests.get_mysqlx_config()
76+
self.schema_name = self.connect_kwargs["schema"]
77+
self.collection_name = "collection_test"
78+
try:
79+
self.session = mysqlx.get_session(self.connect_kwargs)
80+
except mysqlx.Error as err:
81+
self.fail("{0}".format(err))
82+
self.schema = self.session.get_schema(self.schema_name)
83+
self.collection = self.schema.create_collection(self.collection_name)
84+
85+
def tearDown(self):
86+
self.schema.drop_collection(self.collection_name)
87+
self.session.close()
88+
89+
def test_dbdoc_creation(self):
90+
doc_1 = mysqlx.DbDoc({"_id": "1", "name": "Fred", "age": 21})
91+
self.collection.add(doc_1).execute()
92+
self.assertEqual(1, self.collection.count())
93+
94+
# Don't allow _id assignment
95+
self.assertRaises(mysqlx.ProgrammingError,
96+
doc_1.__setitem__, "_id", "1")
97+
98+
doc_2 = {"_id": "2", "name": "Wilma", "age": 33}
99+
self.collection.add(doc_2).execute()
100+
self.assertEqual(2, self.collection.count())
101+
102+
# Copying a DbDoc
103+
doc_3 = self.collection.find().execute().fetch_one()
104+
doc_4 = doc_3.copy("new_id")
105+
self.assertEqual(doc_4["_id"], "new_id")
106+
self.assertNotEqual(doc_3, doc_4)
107+
108+
# Copying a DbDoc without _id
109+
doc_5 = mysqlx.DbDoc({"name": "Fred", "age": 21})
110+
doc_6 = doc_5.copy()
111+
112+
71113
@unittest.skipIf(tests.MYSQL_VERSION < (5, 7, 12), "XPlugin not compatible")
72114
class MySQLxSchemaTests(tests.MySQLxTests):
73115

0 commit comments

Comments
 (0)