Details
-
Bug
-
Resolution: Fixed
-
Major
-
6.6.1, Cheshire-Cat
-
Untriaged
-
1
-
Unknown
Description
DELETE FROM default; |
INSERT INTO default VALUES ("meta:app_uuid_0:e:1", { "app_s": {}}), VALUES ("meta:app_uuid_1:e:1", { "app_s": {}}); |
|
MERGE INTO `default` as t USING (SELECT v.* FROM [ {"country_code": "gb", "key_id": "meta:app_uuid_0:e:1"}, { "country_code": "fr", "key_id": "meta:app_uuid_1:e:1"} ] AS v) AS d ON d.key_id = META(t).id |
WHEN MATCHED THEN UPDATE SET
|
t.app_s.[d.country_code] = {},
|
t.app_s.[d.country_code].[d.key_id] = "xyz"; |
|
SELECT META(d).id, d.* FROM default AS d; |
{
|
"requestID": "72896913-03be-40ca-9098-6bf0ef00dd25", |
"signature": { |
"*": "*", |
"id": "json" |
},
|
"results": [ |
{
|
"app_s": { |
"gb": { |
"meta:app_uuid_0:e:1": "xyz", |
"meta:app_uuid_1:e:1": "xyz" |
}
|
},
|
"id": "meta:app_uuid_0:e:1" |
},
|
{
|
"app_s": { |
"fr": { |
"meta:app_uuid_0:e:1": "xyz", |
"meta:app_uuid_1:e:1": "xyz" |
}
|
},
|
"id": "meta:app_uuid_1:e:1" |
}
|
],
|
"status": "success", |
"metrics": { |
"elapsedTime": "14.918115ms", |
"executionTime": "14.845052ms", |
"resultCount": 2, |
"resultSize": 396 |
}
|
}
|
The above output in correct. The following one is the right one.
|
{
|
"app_s": { |
"gb": { |
"meta:app_uuid_0:e:1": "xyz" |
}
|
},
|
"id": "meta:app_uuid_0:e:1" |
},
|
{
|
"app_s": { |
"fr": { |
"meta:app_uuid_1:e:1": "xyz" |
}
|
},
|
"id": "meta:app_uuid_1:e:1" |
}
|
|
The problem is t.app_s.[d.country_code] = {},
right side is objectConstruct constant. During evaluation it returns from https://github.com/couchbase/query/blob/master/expression/cons_object.go#L51
The value is assigned to left side and later modified. each iteration of UPDATE updates same value and this makes all documents update in correctly.
Same thing can happen ARRAY construct, UPDATE statement.
https://forums.couchbase.com/t/merge-into-seems-to-not-work-correctly/29779/3
This can cause concurrent access of map too