<HTML><BODY><div id="composeWebView_editable_content" data-mailruapp-compose-id="composeWebView_editable_content" style="text-align: left;"><div>Thanks, LGTM.</div><div><br></div><div id="mail-app-auto-signature">

Best regards,<div>Sergos </div>
</div><br><br>Saturday, 14 December 2019, 02:34 +0300 from Vladislav Shpilevoy  <v.shpilevoy@tarantool.org>:<br><div id="composeWebView_previouse_content" data-mailruapp-compose-id="composeWebView_previouse_content"><blockquote id="mail-app-auto-quote" style="border-left-width: 1px; border-left-style: solid; border-left-color: rgb(11, 102, 249); margin: 10px 0px 10px 5px; padding: 0px 0px 0px 10px; display: inherit;" data-darkosha-id="1:3"><div class="js-helper js-readmsg-msg" data-darkosha-id="1:4" style="">
        <style type="text/css" data-darkosha-id="1:5" style=""></style>
        <div data-darkosha-id="1:6" style="">
                <base target="_self" href="https://e.mail.ru/" data-darkosha-id="1:7" style="">
                
            <div id="style_15762800670404139732_BODY" data-darkosha-id="1:8" style="">Hi! Thanks for the review!<br data-darkosha-id="1:9" style="">
<br data-darkosha-id="1:10" style="">
On 09/12/2019 21:18, Sergey Ostanevich wrote:<br data-darkosha-id="1:11" style="">
                                 > Hi! <br data-darkosha-id="1:12" style="">
> <br data-darkosha-id="1:13" style="">
> Thanks for the patch!<br data-darkosha-id="1:14" style="">
> Please, see 4 comments below.<br data-darkosha-id="1:15" style="">
> <br data-darkosha-id="1:16" style="">
> Regards,<br data-darkosha-id="1:17" style="">
> Sergos<br data-darkosha-id="1:18" style="">
> <br data-darkosha-id="1:19" style="">
> <br data-darkosha-id="1:20" style="">
>> diff --git a/src/box/vinyl.c b/src/box/vinyl.c<br data-darkosha-id="1:21" style="">
>> index 767e40006..15a136f81 100644<br data-darkosha-id="1:22" style="">
>> --- a/src/box/vinyl.c<br data-darkosha-id="1:23" style="">
>> +++ b/src/box/vinyl.c<br data-darkosha-id="1:24" style="">
>> @@ -2004,13 +2004,25 @@ request_normalize_ops(struct request *request)<br data-darkosha-id="1:25" style="">
>>                ops_end = mp_encode_str(ops_end, op_name, op_name_len);<br data-darkosha-id="1:26" style="">
>>  <br data-darkosha-id="1:27" style="">
>>                int field_no;<br data-darkosha-id="1:28" style="">
>> -              if (mp_typeof(*pos) == MP_INT) {<br data-darkosha-id="1:29" style="">
>> +              const char *field_name;<br data-darkosha-id="1:30" style="">
>> +              switch (mp_typeof(*pos)) {<br data-darkosha-id="1:31" style="">
>> +              case MP_INT:<br data-darkosha-id="1:32" style="">
>>                        field_no = mp_decode_int(&pos);<br data-darkosha-id="1:33" style="">
>>                        ops_end = mp_encode_int(ops_end, field_no);<br data-darkosha-id="1:34" style="">
>> -              } else {<br data-darkosha-id="1:35" style="">
>> +                      break;<br data-darkosha-id="1:36" style="">
>> +              case MP_UINT:<br data-darkosha-id="1:37" style="">
>>                        field_no = mp_decode_uint(&pos);<br data-darkosha-id="1:38" style="">
>>                        field_no -= request->index_base;<br data-darkosha-id="1:39" style="">
>>                        ops_end = mp_encode_uint(ops_end, field_no);<br data-darkosha-id="1:40" style="">
>> +                      break;<br data-darkosha-id="1:41" style="">
>> +              case MP_STR:<br data-darkosha-id="1:42" style="">
>> +                      field_name = pos;<br data-darkosha-id="1:43" style="">
>> +                      mp_next(&pos);<br data-darkosha-id="1:44" style="">
>> +                      memcpy(ops_end, field_name, pos - field_name);<br data-darkosha-id="1:45" style="">
>> +                      ops_end += pos - field_name;<br data-darkosha-id="1:46" style="">
>> +                      break;<br data-darkosha-id="1:47" style="">
> <br data-darkosha-id="1:48" style="">
> Are you intentionally skip encode/decode here? Is it safe enough?<br data-darkosha-id="1:49" style="">
      <br data-darkosha-id="1:50" style="">
mp_next() does decode. Memcpy is the same as encode here. Just without<br data-darkosha-id="1:51" style="">
'if's. It is safe.<br data-darkosha-id="1:52" style="">
<br data-darkosha-id="1:53" style="">
>> diff --git a/src/box/xrow_update.c b/src/box/xrow_update.c<br data-darkosha-id="1:54" style="">
>> index 123db081a..ecda17544 100644<br data-darkosha-id="1:55" style="">
>> --- a/src/box/xrow_update.c<br data-darkosha-id="1:56" style="">
>> +++ b/src/box/xrow_update.c<br data-darkosha-id="1:57" style="">
>> @@ -412,6 +434,15 @@ xrow_upsert_squash(const char *expr1, const char *expr1_end,<br data-darkosha-id="1:58" style="">
>>                        if (op->opcode != '+' && op->opcode != '-' &&<br data-darkosha-id="1:59" style="">
>>                            op->opcode != '=')<br data-darkosha-id="1:60" style="">
>>                                return NULL;<br data-darkosha-id="1:61" style="">
>> +                      /*<br data-darkosha-id="1:62" style="">
>> +                       * Not terminal operation means, that the<br data-darkosha-id="1:63" style="">
>> +                       * update is not flat, and squash would<br data-darkosha-id="1:64" style="">
>> +                       * need to build a tree of operations to<br data-darkosha-id="1:65" style="">
>> +                       * find matches. That is too complex,<br data-darkosha-id="1:66" style="">
>> +                       * squash is skipped.<br data-darkosha-id="1:67" style="">
>> +                       */<br data-darkosha-id="1:68" style="">
>> +                      if (! xrow_update_op_is_term(op))<br data-darkosha-id="1:69" style="">
>> +                              return NULL;<br data-darkosha-id="1:70" style="">
> <br data-darkosha-id="1:71" style="">
> Please, no space after unary op - and further on in the patch -<br data-darkosha-id="1:72" style="">
> according to $3.1 of<br data-darkosha-id="1:73" style="">
> <a href="https://www.tarantool.io/en/doc/2.2/dev_guide/c_style_guide/" target="_blank" data-darkosha-id="1:74" style="">https://www.tarantool.io/en/doc/2.2/dev_guide/c_style_guide/</a><br data-darkosha-id="1:75" style="">
> <br data-darkosha-id="1:76" style="">
<br data-darkosha-id="1:77" style="">
Ok, here it is:<br data-darkosha-id="1:78" style="">
<br data-darkosha-id="1:79" style="">
==============================================================================<br data-darkosha-id="1:80" style="">
<br data-darkosha-id="1:81" style="">
diff --git a/src/box/xrow_update.c b/src/box/xrow_update.c<br data-darkosha-id="1:82" style="">
index ecda17544..0cee50017 100644<br data-darkosha-id="1:83" style="">
--- a/src/box/xrow_update.c<br data-darkosha-id="1:84" style="">
+++ b/src/box/xrow_update.c<br data-darkosha-id="1:85" style="">
@@ -441,7 +441,7 @@ xrow_upsert_squash(const char *expr1, const char *expr1_end,<br data-darkosha-id="1:86" style="">
                    * find matches. That is too complex,<br data-darkosha-id="1:87" style="">
                    * squash is skipped.<br data-darkosha-id="1:88" style="">
                    */<br data-darkosha-id="1:89" style="">
-                       if (! xrow_update_op_is_term(op))<br data-darkosha-id="1:90" style="">
+                       if (!xrow_update_op_is_term(op))<br data-darkosha-id="1:91" style="">
                           return NULL;<br data-darkosha-id="1:92" style="">
                   if (op->field_no <= prev_field_no)<br data-darkosha-id="1:93" style="">
                           return NULL;<br data-darkosha-id="1:94" style="">
diff --git a/src/box/xrow_update_array.c b/src/box/xrow_update_array.c<br data-darkosha-id="1:95" style="">
index 1cc49f861..57427e39c 100644<br data-darkosha-id="1:96" style="">
--- a/src/box/xrow_update_array.c<br data-darkosha-id="1:97" style="">
+++ b/src/box/xrow_update_array.c<br data-darkosha-id="1:98" style="">
@@ -221,7 +221,7 @@ xrow_update_op_do_array_insert(struct xrow_update_op *op,<br data-darkosha-id="1:99" style="">
 {<br data-darkosha-id="1:100" style="">
   assert(field->type == XUPDATE_ARRAY);<br data-darkosha-id="1:101" style="">
   struct xrow_update_array_item *item;<br data-darkosha-id="1:102" style="">
-       if (! xrow_update_op_is_term(op)) {<br data-darkosha-id="1:103" style="">
+       if (!xrow_update_op_is_term(op)) {<br data-darkosha-id="1:104" style="">
           item = xrow_update_array_extract_item(field, op);<br data-darkosha-id="1:105" style="">
           if (item == NULL)<br data-darkosha-id="1:106" style="">
                   return -1;<br data-darkosha-id="1:107" style="">
@@ -256,7 +256,7 @@ xrow_update_op_do_array_set(struct xrow_update_op *op,<br data-darkosha-id="1:108" style="">
           xrow_update_array_extract_item(field, op);<br data-darkosha-id="1:109" style="">
   if (item == NULL)<br data-darkosha-id="1:110" style="">
           return -1;<br data-darkosha-id="1:111" style="">
-       if (! xrow_update_op_is_term(op))<br data-darkosha-id="1:112" style="">
+       if (!xrow_update_op_is_term(op))<br data-darkosha-id="1:113" style="">
           return xrow_update_op_do_field_set(op, &item->field);<br data-darkosha-id="1:114" style="">
   op->new_field_len = op->arg.set.length;<br data-darkosha-id="1:115" style="">
   /*<br data-darkosha-id="1:116" style="">
@@ -275,7 +275,7 @@ xrow_update_op_do_array_delete(struct xrow_update_op *op,<br data-darkosha-id="1:117" style="">
                          struct xrow_update_field *field)<br data-darkosha-id="1:118" style="">
 {<br data-darkosha-id="1:119" style="">
   assert(field->type == XUPDATE_ARRAY);<br data-darkosha-id="1:120" style="">
-       if (! xrow_update_op_is_term(op)) {<br data-darkosha-id="1:121" style="">
+       if (!xrow_update_op_is_term(op)) {<br data-darkosha-id="1:122" style="">
           struct xrow_update_array_item *item =<br data-darkosha-id="1:123" style="">
                   xrow_update_array_extract_item(field, op);<br data-darkosha-id="1:124" style="">
           if (item == NULL)<br data-darkosha-id="1:125" style="">
@@ -305,7 +305,7 @@ xrow_update_op_do_array_##op_type(struct xrow_update_op *op,                        \<br data-darkosha-id="1:126" style="">
           xrow_update_array_extract_item(field, op);                      \<br data-darkosha-id="1:127" style="">
   if (item == NULL)                                                       \<br data-darkosha-id="1:128" style="">
           return -1;                                                      \<br data-darkosha-id="1:129" style="">
-       if (! xrow_update_op_is_term(op))                                       \<br data-darkosha-id="1:130" style="">
+       if (!xrow_update_op_is_term(op))                                        \<br data-darkosha-id="1:131" style="">
           return xrow_update_op_do_field_##op_type(op, &item->field);      \<br data-darkosha-id="1:132" style="">
   if (item->field.type != XUPDATE_NOP)                                 \<br data-darkosha-id="1:133" style="">
           return xrow_update_err_double(op);                              \<br data-darkosha-id="1:134" style="">
diff --git a/src/box/xrow_update_bar.c b/src/box/xrow_update_bar.c<br data-darkosha-id="1:135" style="">
index 737673e8a..7285c7e2b 100644<br data-darkosha-id="1:136" style="">
--- a/src/box/xrow_update_bar.c<br data-darkosha-id="1:137" style="">
+++ b/src/box/xrow_update_bar.c<br data-darkosha-id="1:138" style="">
@@ -58,7 +58,7 @@ xrow_update_bar_locate(struct xrow_update_op *op,<br data-darkosha-id="1:139" style="">
    * non empty path. This is why op is expected to be not<br data-darkosha-id="1:140" style="">
    * terminal.<br data-darkosha-id="1:141" style="">
    */<br data-darkosha-id="1:142" style="">
-       assert(! xrow_update_op_is_term(op));<br data-darkosha-id="1:143" style="">
+       assert(!xrow_update_op_is_term(op));<br data-darkosha-id="1:144" style="">
   int rc;<br data-darkosha-id="1:145" style="">
   field->type = XUPDATE_BAR;<br data-darkosha-id="1:146" style="">
   field->bar.op = op;<br data-darkosha-id="1:147" style="">
@@ -113,7 +113,7 @@ xrow_update_bar_locate_opt(struct xrow_update_op *op,<br data-darkosha-id="1:148" style="">
    * non empty path. This is why op is expected to be not<br data-darkosha-id="1:149" style="">
    * terminal.<br data-darkosha-id="1:150" style="">
    */<br data-darkosha-id="1:151" style="">
-       assert(! xrow_update_op_is_term(op));<br data-darkosha-id="1:152" style="">
+       assert(!xrow_update_op_is_term(op));<br data-darkosha-id="1:153" style="">
   int rc;<br data-darkosha-id="1:154" style="">
   field->type = XUPDATE_BAR;<br data-darkosha-id="1:155" style="">
   field->bar.op = op;<br data-darkosha-id="1:156" style="">
@@ -245,7 +245,7 @@ xrow_update_op_do_nop_set(struct xrow_update_op *op,<br data-darkosha-id="1:157" style="">
   if (xrow_update_bar_locate_opt(op, field, &is_found, &key_len) != 0)<br data-darkosha-id="1:158" style="">
           return -1;<br data-darkosha-id="1:159" style="">
   op->new_field_len = op->arg.set.length;<br data-darkosha-id="1:160" style="">
-       if (! is_found) {<br data-darkosha-id="1:161" style="">
+       if (!is_found) {<br data-darkosha-id="1:162" style="">
           op->opcode = '!';<br data-darkosha-id="1:163" style="">
           if (mp_typeof(*field->bar.parent) == MP_MAP)<br data-darkosha-id="1:164" style="">
                   op->new_field_len += mp_sizeof_str(key_len);<br data-darkosha-id="1:165" style="">
<br data-darkosha-id="1:166" style="">
==============================================================================<br data-darkosha-id="1:167" style="">
<br data-darkosha-id="1:168" style="">
>> diff --git a/src/box/xrow_update_bar.c b/src/box/xrow_update_bar.c<br data-darkosha-id="1:169" style="">
>> new file mode 100644<br data-darkosha-id="1:170" style="">
>> index 000000000..737673e8a<br data-darkosha-id="1:171" style="">
>> --- /dev/null<br data-darkosha-id="1:172" style="">
>> +++ b/src/box/xrow_update_bar.c<br data-darkosha-id="1:173" style="">
>> +static inline int<br data-darkosha-id="1:174" style="">
>> +xrow_update_bar_locate_opt(struct xrow_update_op *op,<br data-darkosha-id="1:175" style="">
>> +                         struct xrow_update_field *field, bool *is_found,<br data-darkosha-id="1:176" style="">
>> +                         int *key_len_or_index)<br data-darkosha-id="1:177" style="">
>> +{<br data-darkosha-id="1:178" style="">
>> +      /*<br data-darkosha-id="1:179" style="">
>> +       * Bar update is not flat by definition. It always has a<br data-darkosha-id="1:180" style="">
>> +       * non empty path. This is why op is expected to be not<br data-darkosha-id="1:181" style="">
>> +       * terminal.<br data-darkosha-id="1:182" style="">
>> +       */<br data-darkosha-id="1:183" style="">
>> +      assert(! xrow_update_op_is_term(op));<br data-darkosha-id="1:184" style="">
>> +      int rc;<br data-darkosha-id="1:185" style="">
>> +      field->type = XUPDATE_BAR;<br data-darkosha-id="1:186" style="">
>> +      field->bar.op = op;<br data-darkosha-id="1:187" style="">
>> +      field->bar.path = op->lexer.src + op->lexer.offset;<br data-darkosha-id="1:188" style="">
>> +      field->bar.path_len = op->lexer.src_len - op->lexer.offset;<br data-darkosha-id="1:189" style="">
>> +      const char *pos = field->data;<br data-darkosha-id="1:190" style="">
>> +      struct json_token token;<br data-darkosha-id="1:191" style="">
>> +      do {<br data-darkosha-id="1:192" style="">
>> +              rc = json_lexer_next_token(&op->lexer, &token);<br data-darkosha-id="1:193" style="">
>> +              if (rc != 0)<br data-darkosha-id="1:194" style="">
>> +                      return xrow_update_err_bad_json(op, rc);<br data-darkosha-id="1:195" style="">
>> +<br data-darkosha-id="1:196" style="">
>> +              switch (token.type) {<br data-darkosha-id="1:197" style="">
>> +              case JSON_TOKEN_END:<br data-darkosha-id="1:198" style="">
>> +                      *is_found = true;<br data-darkosha-id="1:199" style="">
>> +                      field->bar.point = pos;<br data-darkosha-id="1:200" style="">
>> +                      mp_next(&pos);<br data-darkosha-id="1:201" style="">
>> +                      field->bar.point_size = pos - field->bar.point;<br data-darkosha-id="1:202" style="">
>> +                      return 0;<br data-darkosha-id="1:203" style="">
>> +              case JSON_TOKEN_NUM:<br data-darkosha-id="1:204" style="">
>> +                      field->bar.parent = pos;<br data-darkosha-id="1:205" style="">
>> +                      *key_len_or_index = token.num;<br data-darkosha-id="1:206" style="">
>> +                      rc = tuple_field_go_to_index(&pos, token.num);<br data-darkosha-id="1:207" style="">
>> +                      break;<br data-darkosha-id="1:208" style="">
>> +              case JSON_TOKEN_STR:<br data-darkosha-id="1:209" style="">
>> +                      field->bar.parent = pos;<br data-darkosha-id="1:210" style="">
>> +                      *key_len_or_index = token.len;<br data-darkosha-id="1:211" style="">
>> +                      rc = tuple_field_go_to_key(&pos, token.str, token.len);<br data-darkosha-id="1:212" style="">
>> +                      break;<br data-darkosha-id="1:213" style="">
>> +              default:<br data-darkosha-id="1:214" style="">
>> +                      assert(token.type == JSON_TOKEN_ANY);<br data-darkosha-id="1:215" style="">
>> +                      rc = op->lexer.symbol_count - 1;<br data-darkosha-id="1:216" style="">
>> +                      return xrow_update_err_bad_json(op, rc);<br data-darkosha-id="1:217" style="">
>> +              }<br data-darkosha-id="1:218" style="">
>> +      } while (rc == 0);<br data-darkosha-id="1:219" style="">
>> +      assert(rc == -1);<br data-darkosha-id="1:220" style="">
>> +      /* Ensure, that 'token' is next to last path part. */<br data-darkosha-id="1:221" style="">
>> +      struct json_token tmp_token;<br data-darkosha-id="1:222" style="">
>> +      rc = json_lexer_next_token(&op->lexer, &tmp_token);<br data-darkosha-id="1:223" style="">
>> +      if (rc != 0)<br data-darkosha-id="1:224" style="">
>> +              return xrow_update_err_bad_json(op, rc);<br data-darkosha-id="1:225" style="">
>> +      if (tmp_token.type != JSON_TOKEN_END)<br data-darkosha-id="1:226" style="">
>> +              return xrow_update_err_no_such_field(op);<br data-darkosha-id="1:227" style="">
>> +<br data-darkosha-id="1:228" style="">
>> +      *is_found = false;<br data-darkosha-id="1:229" style="">
>> +      if (token.type == JSON_TOKEN_NUM) {<br data-darkosha-id="1:230" style="">
>> +              const char *tmp = field->bar.parent;<br data-darkosha-id="1:231" style="">
>> +              if (mp_typeof(*tmp) != MP_ARRAY) {<br data-darkosha-id="1:232" style="">
>> +                      return xrow_update_err(op, "can not access by index a "\<br data-darkosha-id="1:233" style="">
>> +                                             "non-array field");<br data-darkosha-id="1:234" style="">
>> +              }<br data-darkosha-id="1:235" style="">
>> +              uint32_t size = mp_decode_array(&tmp);<br data-darkosha-id="1:236" style="">
>> +              if ((uint32_t) token.num > size)<br data-darkosha-id="1:237" style="">
>> +                      return xrow_update_err_no_such_field(op);<br data-darkosha-id="1:238" style="">
> <br data-darkosha-id="1:239" style="">
> IMHO there will be more informative to mention the array and an index<br data-darkosha-id="1:240" style="">
> that is out of bounds.<br data-darkosha-id="1:241" style="">
> <br data-darkosha-id="1:242" style="">
<br data-darkosha-id="1:243" style="">
Well, xrow_update_err_no_such_field() does it. It adds the whole<br data-darkosha-id="1:244" style="">
path to the error message. So a user will see what a path caused<br data-darkosha-id="1:245" style="">
the problem.<br data-darkosha-id="1:246" style="">
<br data-darkosha-id="1:247" style="">
>> +              /*<br data-darkosha-id="1:248" style="">
>> +               * The updated point is in an array, its position<br data-darkosha-id="1:249" style="">
>> +               * was not found, and its index is <= size. The<br data-darkosha-id="1:250" style="">
>> +               * only way how can that happen - the update tries<br data-darkosha-id="1:251" style="">
>> +               * to append a new array element. The following<br data-darkosha-id="1:252" style="">
>> +               * code tries to find the array's end.<br data-darkosha-id="1:253" style="">
>> +               */<br data-darkosha-id="1:254" style="">
>> +              assert((uint32_t) token.num == size);<br data-darkosha-id="1:255" style="">
>> +              if (field->bar.parent == field->data) {<br data-darkosha-id="1:256" style="">
>> +                      /*<br data-darkosha-id="1:257" style="">
>> +                       * Optimization for the case when the path<br data-darkosha-id="1:258" style="">
>> +                       * is short. So parent of the updated<br data-darkosha-id="1:259" style="">
>> +                       * point is the field itself. It allows<br data-darkosha-id="1:260" style="">
>> +                       * not to decode anything at all. It is<br data-darkosha-id="1:261" style="">
>> +                       * worth doing, since the paths are<br data-darkosha-id="1:262" style="">
>> +                       * usually short.<br data-darkosha-id="1:263" style="">
>> +                       */<br data-darkosha-id="1:264" style="">
>> +                      field->bar.point = field->data + field->size;<br data-darkosha-id="1:265" style="">
>> +              } else {<br data-darkosha-id="1:266" style="">
>> +                      field->bar.point = field->bar.parent;<br data-darkosha-id="1:267" style="">
>> +                      mp_next(&field->bar.point);<br data-darkosha-id="1:268" style="">
>> +              }<br data-darkosha-id="1:269" style="">
>> +              field->bar.point_size = 0;<br data-darkosha-id="1:270" style="">
>> +      } else {<br data-darkosha-id="1:271" style="">
>> +              assert(token.type == JSON_TOKEN_STR);<br data-darkosha-id="1:272" style="">
>> +              field->bar.new_key = token.str;<br data-darkosha-id="1:273" style="">
>> +              field->bar.new_key_len = token.len;<br data-darkosha-id="1:274" style="">
>> +              if (mp_typeof(*field->bar.parent) != MP_MAP) {<br data-darkosha-id="1:275" style="">
>> +                      return xrow_update_err(op, "can not access by key a "\<br data-darkosha-id="1:276" style="">
>> +                                             "non-map field");<br data-darkosha-id="1:277" style="">
>> +              }<br data-darkosha-id="1:278" style="">
>> +      }<br data-darkosha-id="1:279" style="">
>> +      return 0;<br data-darkosha-id="1:280" style="">
>> +}<br data-darkosha-id="1:281" style="">
>> +<br data-darkosha-id="1:282" style="">
>> +/**<br data-darkosha-id="1:283" style="">
>> + * Nop fields are those which are not updated. And when they<br data-darkosha-id="1:284" style="">
>> + * receive an update via one of xrow_update_op_do_nop_* functions,<br data-darkosha-id="1:285" style="">
>> + * it means, that there is a non terminal path digging inside this<br data-darkosha-id="1:286" style="">
>> + * not updated field. It turns nop field into a bar field. How<br data-darkosha-id="1:287" style="">
>> + * exactly - depends on a concrete operation.<br data-darkosha-id="1:288" style="">
>> + */<br data-darkosha-id="1:289" style="">
>> +<br data-darkosha-id="1:290" style="">
>> +int<br data-darkosha-id="1:291" style="">
>> +xrow_update_op_do_nop_insert(struct xrow_update_op *op,<br data-darkosha-id="1:292" style="">
>> +                           struct xrow_update_field *field)<br data-darkosha-id="1:293" style="">
>> +{<br data-darkosha-id="1:294" style="">
>> +      assert(op->opcode == '!');<br data-darkosha-id="1:295" style="">
>> +      assert(field->type == XUPDATE_NOP);<br data-darkosha-id="1:296" style="">
> <br data-darkosha-id="1:297" style="">
> Hmm. Do you expect to handle all possible cases in debug mode? <br data-darkosha-id="1:298" style="">
> Otherwise here should be some sort of gaceful fail to make prod more<br data-darkosha-id="1:299" style="">
> stable.<br data-darkosha-id="1:300" style="">
> <br data-darkosha-id="1:301" style="">
<br data-darkosha-id="1:302" style="">
In Tarantool we usually rely on the tests and debug mode. Concretely<br data-darkosha-id="1:303" style="">
this case I covered with tests on 100% not including OOM (we can't<br data-darkosha-id="1:304" style="">
test malloc failures, basically). This is done to not slowdown release<br data-darkosha-id="1:305" style="">
build with never passing checks such as this. Removal of assertion<br data-darkosha-id="1:306" style="">
checks from release gives very significant perf impact. However in some<br data-darkosha-id="1:307" style="">
places which are not hot paths there is a thing related to what you<br data-darkosha-id="1:308" style="">
mean: <a href="https://github.com/tarantool/tarantool/issues/2571" target="_blank" data-darkosha-id="1:309" style="">https://github.com/tarantool/tarantool/issues/2571</a><br data-darkosha-id="1:310" style="">
</div>
            
        
                <base target="_self" href="https://e.mail.ru/" data-darkosha-id="1:311" style="">
        </div>

        
</div></blockquote></div></div></BODY></HTML>