WL#10682: Mysqlx.CRUD.Update on top level document

Affects: Server-8.0   —   Status: Complete   —   Priority: Medium

Motivation
==========

The Mysqlx.CRUD.Update doesn't support updating an existing
*full* document, only parts of it.

The intention was that any update (special case *full* document) could also
overwrite the _id field and lead implicit change of identity (and possible
reshuffeling of data in sharding).

Current Behaviour
=================

The 'Mysqlx.CRUD.UpdateOperation' supports ITEM_REMOVE, ITEM_SET, ITEM_REPLACE,
ARRAY_INSERT, ARRAY_APPEND commands:

    message UpdateOperation {
      enum UpdateType {
        ...
        ITEM_SET = 3;       // sets the new value on the identified path
        ITEM_REPLACE = 4;   // replaces a value if the path exists
        ITEM_MERGE = 5;     // source and value must be documents
        ...
      }
      required Mysqlx.Expr.ColumnIdentifier source = 1;
      required UpdateType operation = 2;
      optional Mysqlx.Expr.Expr value = 3;
      ...
    }

The operations require:

* non-empty document-path
* value

Expected Behaviour
==================

Allow specifying a empty document-path to operate on the whole document.

Any operation done on existing document must preserved _id field.
Functional requirements
=======================

1. The Update commands **(ITEM_REMOVE, ITEM_SET, ITEM_REPLACE, ARRAY_INSERT, 
   ARRAY_APPEND)** must continue working as is for any non-empty document paths 
2. The Update commands **(ITEM_REMOVE, ITEM_SET, ITEM_REPLACE, ARRAY_INSERT, 
   ARRAY_APPEND)** must allow an empty document path to be specified, which would
   replace the full document with the provided one
3. If resulting value is a non-document, an error must be generated
4. If resulting document contains an **_id** value different from the original,
   it must be ignored (original **_id** must be restored).
This is an incremental change on the existing operations of the 
Mysqlx.CRUD.Update command.

The command only applies to JSON, in both Collections and Tables (on JSON 
columns).

Previously, ITEM_ITEM_REMOVE, ITEM_SET, ITEM_REPLACE, ARRAY_INSERT, ARRAY_APPEND
commands were forbidden on the top level document to avoid changes to the _id field. This WL changes that behaviour so that in Collections, 
this case is handled by explicitly overwriting the _id field of the document 
with the value of the original _id column, thus preserving the value of the 
original _id field. This precaution is not needed for tables.

ITEM_MERGE operations on user provided value, not on document_path. Any attempt of setting the document_path must return an error.


Current behaviour Mysqlx.Crud.Update
====================================

Input parameters:

* document_path1...
* value1...
* operations

Algorithm:

    if (is_path_empty(document_path1...))
      return ERROR
    else
      UPDATE TABLE coll SET doc=operations(doc, document_path1..., value1...);


New behaviour of Mysqlx.Crud.Update
===================================

Input parameters:

* operations
* document_path1...
* value1...

Algorithm:

    if (has_merge_non_empty_path(operations, document_path1...))
      return ERROR
    UPDATE TABLE tbl SET doc=JSON_SET(
      operations(doc, document_path1..., value1...),
      '$._id', doc->"$._id");


Error and Warnings
==================

|Property       |Value                                         |
|---------------|----------------------------------------------|
|Error code     |ER_X_BAD_UPDATE_DATA                          |
|Error text     |Unexpected source for ITEM_MERGE operation    |
|New error code |No                                            |

Example
=======

DevAPI example of two operations made on 'coll' collection:

    coll.modify("true")
      .set(document_path1, value1)
      .unset(document_path2).execute()

Generated SQL:

    UPDATE TABLE coll SET doc=JSON_SET(
        JSON_REMOVE(
            JSON_SET(doc, document_path1, value1),
            document_path2),
        '$._id',  doc->'$._id'));