Skip to content

Commit 3a53205

Browse files
committed
BUG27602636: EXPRESSIONS IN TABLE.UPDATE().SET() RAISES AN EXCEPTION: UNKNOWN COLUMN 'DOC'
A DocumentPathItem were missing the column name, and it was evaluated to the default name 'doc' in the server side. With this patch the column name is taken from the first parameter which generally indicates the column or json_doc.
1 parent b9d2fdd commit 3a53205

File tree

2 files changed

+31
-10
lines changed

2 files changed

+31
-10
lines changed

lib/mysqlx/expr.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,9 +413,10 @@ def escape_literal(string):
413413

414414

415415
class ExprParser(object):
416-
def __init__(self, string, allow_relational=False):
416+
def __init__(self, string, allow_relational=True):
417417
self.string = string
418418
self.tokens = []
419+
self.path_name_queue = []
419420
self.pos = 0
420421
self._allow_relational_columns = allow_relational
421422
self.placeholder_name_to_position = {}
@@ -624,8 +625,9 @@ def assert_cur_token(self, token_type):
624625
"tokens left".format(token_type, self.pos))
625626
if self.tokens[self.pos].token_type != token_type:
626627
raise ValueError("Expected token type {0} at pos {1} but found "
627-
"type {2}".format(token_type, self.pos,
628-
self.tokens[self.pos]))
628+
"type {2}, on tokens {3}"
629+
"".format(token_type, self.pos,
630+
self.tokens[self.pos], self.tokens))
629631

630632
def cur_token_type_is(self, token_type):
631633
return self.pos_token_type_is(self.pos, token_type)
@@ -656,13 +658,24 @@ def paren_expr_list(self):
656658
list and return a list of Expr objects.
657659
"""
658660
exprs = []
661+
path_name_added = False
659662
self.consume_token(TokenType.LPAREN)
660663
if not self.cur_token_type_is(TokenType.RPAREN):
661-
exprs.append(self._expr().get_message())
664+
msg_expr = self._expr().get_message()
665+
if hasattr(msg_expr, "identifier") and msg_expr.identifier.name:
666+
self.path_name_queue.insert(0, msg_expr.identifier.name)
667+
path_name_added = True
668+
elif not hasattr(msg_expr, "identifier") and \
669+
"identifier" in msg_expr and "name" in msg_expr["identifier"]:
670+
self.path_name_queue.insert(0, msg_expr["identifier"]["name"])
671+
path_name_added = True
672+
exprs.append(msg_expr)
662673
while self.cur_token_type_is(TokenType.COMMA):
663674
self.pos += 1
664675
exprs.append(self._expr().get_message())
665676
self.consume_token(TokenType.RPAREN)
677+
if path_name_added:
678+
self.path_name_queue.pop()
666679
return exprs
667680

668681
def identifier(self):
@@ -740,6 +753,8 @@ def document_field(self):
740753
doc_path_item["value"] = self.consume_token(TokenType.IDENT)
741754
col_id["document_path"].extend([doc_path_item.get_message()])
742755
col_id["document_path"].extend(self.document_path())
756+
if self.path_name_queue:
757+
col_id["name"] = self.path_name_queue[0]
743758
expr = Message("Mysqlx.Expr.Expr")
744759
expr["type"] = mysqlxpb_enum("Mysqlx.Expr.Expr.Type.IDENT")
745760
expr["identifier"] = col_id

tests/test_mysqlx_crud.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2504,15 +2504,15 @@ def test_insert(self):
25042504

25052505
def test_update(self):
25062506
self.session.sql("CREATE TABLE {0}.test(age INT, name "
2507-
"VARCHAR(50), gender CHAR(1))"
2507+
"VARCHAR(50), gender CHAR(1), `info` json DEFAULT NULL)"
25082508
"".format(self.schema_name)).execute()
25092509
table = self.schema.get_table("test")
25102510

2511-
result = table.insert("age", "name") \
2512-
.values(21, 'Fred') \
2513-
.values(28, 'Barney') \
2514-
.values(42, 'Wilma') \
2515-
.values(67, 'Betty').execute()
2511+
result = table.insert("age", "name", "info") \
2512+
.values(21, 'Fred', {"married": True, "sons": 0}) \
2513+
.values(28, 'Barney', {"married": True, "sons": 1}) \
2514+
.values(42, 'Wilma', {"married": True, "sons": 0}) \
2515+
.values(67, 'Betty', {"married": True, "sons": 1}).execute()
25162516

25172517
result = table.update().set("age", 25).where("age == 21").execute()
25182518
self.assertEqual(1, result.get_affected_items_count())
@@ -2521,6 +2521,12 @@ def test_update(self):
25212521
result = table.update().set("age", 25)
25222522
self.assertRaises(mysqlx.ProgrammingError, result.execute)
25232523

2524+
# Update with a mysqlx expression
2525+
statement = table.update()
2526+
statement.set("info", mysqlx.expr("JSON_SET(info, '$.sons', $.sons * 2)"))
2527+
result = statement.where( "name = 'Barney' or name = 'Betty'").execute()
2528+
assert (2 == result.get_affected_items_count())
2529+
25242530
drop_table(self.schema, "test")
25252531

25262532
def test_delete(self):

0 commit comments

Comments
 (0)