Skip to content

Commit 099e3f1

Browse files
committed
BUG#34260344: Disallow empty strings in collection fields
Connector/Python allows empty strings ("") in the collection fields used in methods chained with Collection.modify(). With this patch, this behavior is not allowed. For replacing the entire document the "$" character should be used instead. Change-Id: I519a6b0ec41b6f344aaf4bab5e5a89d5475954d9
1 parent 07e3d17 commit 099e3f1

File tree

4 files changed

+45
-5
lines changed

4 files changed

+45
-5
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ v8.0.30
1717
- WL#15035: Enforce PEP 7 and PEP 8 coding style
1818
- WL#14822: Refactor the authentication plugin mechanism
1919
- WL#14815: Support OpenSSL 3.0
20+
- BUG#34260344: Disallow empty strings in collection fields
2021
- BUG#34231226: Generated classes do not work with the latest Protobuf
2122
- BUG#34228442: Fix NO_BACKSLASH_ESCAPES SQL mode support in c-ext
2223
- BUG#34223015: Invalidate the usage of non-compatible cursor types

lib/mysqlx/expr.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,10 @@ def docpath_array_loc(self):
776776
)
777777

778778
def document_field(self):
779+
if not self.tokens:
780+
raise ValueError("Empty string cannot be used as document field")
781+
if self.cur_token_type_is(TokenType.DOLLAR):
782+
self.consume_token(TokenType.DOLLAR)
779783
col_id = Message("Mysqlx.Expr.ColumnIdentifier")
780784
if self.cur_token_type_is(TokenType.IDENT):
781785
doc_path_item = Message("Mysqlx.Expr.DocumentPathItem")

lib/mysqlx/statement.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -718,17 +718,20 @@ class UpdateSpec:
718718
update_type (int): The update type.
719719
source (str): The source.
720720
value (Optional[str]): The value.
721+
722+
Raises:
723+
ProgrammingError: If `source` is invalid.
721724
"""
722725

723726
def __init__(self, update_type, source, value=None):
724727
if update_type == mysqlxpb_enum("Mysqlx.Crud.UpdateOperation.UpdateType.SET"):
725728
self._table_set(source, value)
726729
else:
727730
self.update_type = update_type
728-
self.source = source
729-
if len(source) > 0 and source[0] == "$":
730-
self.source = source[1:]
731-
self.source = ExprParser(self.source, False).document_field().identifier
731+
try:
732+
self.source = ExprParser(source, False).document_field().identifier
733+
except ValueError as err:
734+
raise ProgrammingError(f"{err}")
732735
self.value = value
733736

734737
def _table_set(self, source, value):
@@ -897,7 +900,7 @@ def patch(self, doc):
897900
)
898901
self._update_ops["patch"] = UpdateSpec(
899902
mysqlxpb_enum("Mysqlx.Crud.UpdateOperation.UpdateType.MERGE_PATCH"),
900-
"",
903+
"$",
901904
doc.expr() if isinstance(doc, ExprParser) else doc,
902905
)
903906
self._changed = True

tests/test_mysqlx_crud.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1889,6 +1889,38 @@ def test_modify(self):
18891889
result = collection.modify("").unset(["young"])
18901890
self.assertRaises(mysqlx.ProgrammingError, result.execute)
18911891

1892+
# test empty strings in collection fields
1893+
for string in ("", " ", " "):
1894+
self.assertRaises(
1895+
mysqlx.ProgrammingError,
1896+
collection.modify("$._id == 1").set,
1897+
string,
1898+
{"name": "Maria", "age": 78},
1899+
)
1900+
self.assertRaises(
1901+
mysqlx.ProgrammingError,
1902+
collection.modify("$._id == 1").unset,
1903+
string,
1904+
)
1905+
self.assertRaises(
1906+
mysqlx.ProgrammingError,
1907+
collection.modify("$._id == 1").change,
1908+
string,
1909+
{"name": "Maria", "age": 78},
1910+
)
1911+
self.assertRaises(
1912+
mysqlx.ProgrammingError,
1913+
collection.modify("$._id == 1").array_insert,
1914+
string,
1915+
[2, 3, 4],
1916+
)
1917+
self.assertRaises(
1918+
mysqlx.ProgrammingError,
1919+
collection.modify("$._id == 1").array_append,
1920+
string,
1921+
[2, 3, 4],
1922+
)
1923+
18921924
self.schema.drop_collection(collection_name)
18931925

18941926
@unittest.skipIf(tests.MYSQL_VERSION < (8, 0, 4), "Unavailable")

0 commit comments

Comments
 (0)