[Tarantool-patches] [PATCH v2 2/4] tuple: pass tuple format to xrow_update_*_store()

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Tue Feb 11 00:18:45 MSK 2020


Thanks for the review!

On 10/02/2020 17:51, Nikita Pettik wrote:
> On 04 Feb 23:53, Vladislav Shpilevoy wrote:
>> diff --git a/src/box/xrow_update_array.c b/src/box/xrow_update_array.c
>> index b97c23d77..717466be7 100644
>> --- a/src/box/xrow_update_array.c
>> +++ b/src/box/xrow_update_array.c
>> @@ -31,6 +31,7 @@
>>  #include "xrow_update_field.h"
>>  #include "msgpuck.h"
>>  #include "fiber.h"
>> +#include "tuple_format.h"
>>  
>>  /**
>>   * Make sure @a op contains a valid field number to where the
>> @@ -259,26 +260,49 @@ xrow_update_array_sizeof(struct xrow_update_field *field)
>>  }
>>  
>>  uint32_t
>> -xrow_update_array_store(struct xrow_update_field *field, char *out,
>> -			char *out_end)
>> +xrow_update_array_store(struct xrow_update_field *field,
>> +			struct json_tree *format_tree,
>> +			struct json_token *this_node, char *out, char *out_end)
>>  {
>>  	assert(field->type == XUPDATE_ARRAY);
>>  	char *out_begin = out;
>>  	out = mp_encode_array(out, xrow_update_rope_size(field->array.rope));
>> -	uint32_t total_field_count = 0;
>>  	struct xrow_update_rope_iter it;
>>  	xrow_update_rope_iter_create(&it, field->array.rope);
>>  	struct xrow_update_rope_node *node = xrow_update_rope_iter_start(&it);
>> -	for (; node != NULL; node = xrow_update_rope_iter_next(&it)) {
>> -		struct xrow_update_array_item *item =
>> -			xrow_update_rope_leaf_data(node);
>> -		uint32_t field_count = xrow_update_rope_leaf_size(node);
>> -		out += xrow_update_field_store(&item->field, out, out_end);
>> -		assert(item->tail_size == 0 || field_count > 1);
>> -		memcpy(out, item->field.data + item->field.size,
>> -		       item->tail_size);
>> -		out += item->tail_size;
>> -		total_field_count += field_count;
>> +	uint32_t total_field_count = 0;
>> +	if (this_node == NULL) {
>> +		for (; node != NULL; node = xrow_update_rope_iter_next(&it)) {
>> +			struct xrow_update_array_item *item =
>> +				xrow_update_rope_leaf_data(node);
>> +			uint32_t field_count = xrow_update_rope_leaf_size(node);
>> +			out += xrow_update_field_store(&item->field, NULL, NULL,
>> +						       out, out_end);
>> +			assert(item->tail_size == 0 || field_count > 1);
>> +			memcpy(out, item->field.data + item->field.size,
>> +			       item->tail_size);
>> +			out += item->tail_size;
>> +			total_field_count += field_count;
>> +		}
>> +	} else {
>> +		struct json_token token;
>> +		token.type = JSON_TOKEN_NUM;
>> +		token.num = 0;
>> +		struct json_token *next_node;
>> +		for (; node != NULL; node = xrow_update_rope_iter_next(&it)) {
>> +			struct xrow_update_array_item *item =
>> +				xrow_update_rope_leaf_data(node);
>> +			next_node = json_tree_lookup(format_tree, this_node, &token);
>> +			uint32_t field_count = xrow_update_rope_leaf_size(node);
>> +			out += xrow_update_field_store(&item->field, format_tree,
>> +						       next_node, out, out_end);
>> +			assert(item->tail_size == 0 || field_count > 1);
>> +			memcpy(out, item->field.data + item->field.size,
>> +			       item->tail_size);
>> +			out += item->tail_size;
>> +			token.num += field_count;
>> +			total_field_count += field_count;
>> +		}
> 
> IMHO this code duplication looks a bit rough. What about next refactoring:

I did it intentionally to avoid comparison of 'this_node' with NULL on each
iteration. But ok, applied your diff.

I also found a bug in this patch - I used tuple index base 0 for JSON
paths lookup in xrow_update_bar/route.c. The test in the last patch was
broken because of this, but I missed that, because it was incorrect as well.
Fixed the bug here, and the test there. Diff below.

================================================================================
diff --git a/src/box/xrow_update_bar.c b/src/box/xrow_update_bar.c
index b4a98978a..f104a08da 100644
--- a/src/box/xrow_update_bar.c
+++ b/src/box/xrow_update_bar.c
@@ -436,7 +436,7 @@ xrow_update_bar_store(struct xrow_update_field *field,
 		if (this_node != NULL) {
 			this_node = json_tree_lookup_path(
 				format_tree, this_node, field->bar.path,
-				field->bar.path_len, 0);
+				field->bar.path_len, TUPLE_INDEX_BASE);
 		}
diff --git a/src/box/xrow_update_route.c b/src/box/xrow_update_route.c
index 122f0329e..d2b8979b8 100644
--- a/src/box/xrow_update_route.c
+++ b/src/box/xrow_update_route.c
@@ -384,7 +384,7 @@ xrow_update_route_store(struct xrow_update_field *field,
 	if (this_node != NULL) {
 		this_node = json_tree_lookup_path(
 			format_tree, this_node, field->route.path,
-			field->route.path_len, 0);
+			field->route.path_len, TUPLE_INDEX_BASE);
 	}
================================================================================

Additionally, I realized, that I don't need the json tree in upsert squash.
Indeed, it merges operations, not fields. Providing type of a result field
won't help here, because anyway it will be provided, when the upsert is
merged with some real tuple. Diff below.

================================================================================
diff --git a/src/box/xrow_update.c b/src/box/xrow_update.c
index ac8c9d303..3cdcc9ee7 100644
--- a/src/box/xrow_update.c
+++ b/src/box/xrow_update.c
@@ -467,10 +467,6 @@ xrow_upsert_squash(const char *expr1, const char *expr1_end,
 
 	uint32_t op_count[2] = {update[0].op_count, update[1].op_count};
 	uint32_t op_no[2] = {0, 0};
-	struct json_tree *format_tree = &format->fields;
-	struct json_token *root = &format_tree->root;
-	struct json_token token;
-	token.type = JSON_TOKEN_NUM;
 	while (op_no[0] < op_count[0] || op_no[1] < op_count[1]) {
 		res_count++;
 		struct xrow_update_op *op[2] = {update[0].ops + op_no[0],
@@ -525,13 +521,10 @@ xrow_upsert_squash(const char *expr1, const char *expr1_end,
 		res_ops = mp_encode_array(res_ops, 3);
 		res_ops = mp_encode_str(res_ops,
 					(const char *)&op[0]->opcode, 1);
-		token.num = op[0]->field_no;
-		res_ops = mp_encode_uint(res_ops, token.num +
-					 update[0].index_base);
-		struct json_token *this_node =
-			json_tree_lookup(format_tree, root, &token);
-		xrow_update_op_store_arith(&res, format_tree, this_node, NULL,
-					   res_ops);
+		res_ops = mp_encode_uint(res_ops,
+					 op[0]->field_no +
+						 update[0].index_base);
+		xrow_update_op_store_arith(&res, NULL, NULL, NULL, res_ops);
 		res_ops += xrow_update_arg_arith_sizeof(&res.arg.arith);
 		mp_next(&expr[0]);
 		mp_next(&expr[1]);
================================================================================


More information about the Tarantool-patches mailing list