>From Shahrzad Shirazi <[email protected]>:

Shahrzad Shirazi has submitted this change. ( 
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21205?usp=email )

Change subject: [ASTERIXDB-3770][COMP] Fix incorrect Result When Updating a 
Full Object
......................................................................

[ASTERIXDB-3770][COMP] Fix incorrect Result When Updating a Full Object

- user model changes: yes
- storage format changes: no
- interface changes: no

Ext-ref: MB-70961


Change-Id: I07a2fc3c76afe1f26d95225e4010b57f662f5ef0
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21205
Integration-Tests: Jenkins <[email protected]>
Tested-by: Ali Alsuliman <[email protected]>
Reviewed-by: Ali Alsuliman <[email protected]>
---
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.12.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.13.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.14.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.15.query.sqlpp
M 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/simple-case/simple-case.22.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/complex-case/complex-case.13.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/complex-case/complex-case.15.adm
M 
asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.19.adm
M 
asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.20.adm
M 
asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.21.adm
M 
asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.23.adm
M 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/ChangeExpression.java
M 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SetExpressionTree.java
M 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppChangeExprToSelectExprVisitor.java
14 files changed, 345 insertions(+), 20 deletions(-)

Approvals:
  Ali Alsuliman: Looks good to me, approved; Verified
  Jenkins: Verified

Objections:
  Anon. E. Moose #1000171: Violations found




diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.12.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.12.ddl.sqlpp
new file mode 100644
index 0000000..b4a4b09
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.12.ddl.sqlpp
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+DROP DATAVERSE test IF EXISTS;
+CREATE DATAVERSE test;
+USE test;
+
+CREATE TYPE UserType2 AS {
+  userId: int
+};
+
+CREATE DATASET UserTypes2(UserType2) PRIMARY KEY userId;
+
+
+INSERT INTO UserTypes2([
+  {
+    "userId": 3,
+    "email": "[email protected]",
+    "username": "carol",
+    "isActive": true,
+    "roles": [
+      { "roleId": "role1", "roleName": "moderator" }
+    ],
+    "c_purchase_history": {
+      "c_recent_orders": [
+        { "orderId": "101"} ,
+        { "orderId": "102" } ,
+        { "orderId": "103"}
+      ]
+    }
+  },
+  {
+    "userId": 4,
+    "email": "[email protected]",
+    "username": "carol",
+    "isActive": true,
+    "roles": [
+      { "roleId": "role1", "roleName": "moderator" }
+    ],
+    "c_purchase_history": {
+      "c_recent_orders": [
+        { "orderId": "101"} ,
+        { "orderId": "102" } ,
+        { "orderId": "103"}
+      ]
+    }
+  },{
+    "userId": 5,
+    "email": "[email protected]",
+    "username": "carol",
+    "isActive": true,
+    "roles": [
+      { "roleId": "role1", "roleName": "moderator" }
+    ],
+    "c_purchase_history": {
+      "c_recent_orders": [
+        { "orderId": "101"} ,
+        { "orderId": "102" } ,
+        { "orderId": "103"}
+      ]
+    }
+  }
+]);
+
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.13.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.13.query.sqlpp
new file mode 100644
index 0000000..113713d
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.13.query.sqlpp
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+UPDATE UserTypes2 AS u
+set u.c_purchase_history={"a1":33}
+set u.c_purchase_history2={"a2":33}
+WHERE u.userId= 3;
+
+UPDATE UserTypes2 AS u
+set u.c_purchase_history.c_recent_orders=["a","5"]
+set u.a="p"
+set u.isActive=Missing
+WHERE u.userId= 4;
+
+
+UPDATE UserTypes2 AS u
+set u={"userId":5}
+WHERE u.userId= 5;
+
+
+select * from UserTypes2
+order by userId;
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.14.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.14.ddl.sqlpp
new file mode 100644
index 0000000..1e7bf85
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.14.ddl.sqlpp
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+DROP DATAVERSE test IF EXISTS;
+CREATE DATAVERSE test;
+USE test;
+
+CREATE TYPE UserType2 AS {
+  userId: int
+};
+
+CREATE DATASET UserTypes2(UserType2) PRIMARY KEY userId;
+
+
+INSERT INTO UserTypes2([
+  {
+    "userId": 3,
+    "email": "[email protected]",
+    "username": "carol",
+    "isActive": true,
+    "roles": [
+      { "roleId": "role1", "roleName": "moderator" },
+      { "roleId": "role2", "roleName": "moderator" }
+
+
+    ],
+    "c_purchase_history": {
+      "c_recent_orders": [
+        { "orderId": "101"} ,
+        { "orderId": "102" } ,
+        { "orderId": "103"}
+      ]
+    }
+  },
+  {
+    "userId": 4,
+    "email": "[email protected]",
+    "username": "carol",
+    "isActive": true,
+    "roles": [
+      { "roleId": "role1", "roleName": "moderator" }
+    ],
+    "c_purchase_history": {
+      "c_recent_orders": [
+        { "orderId": "101"} ,
+        { "orderId": "102" } ,
+        { "orderId": "103"}
+      ]
+    }
+  },{
+    "userId": 5,
+    "email": "[email protected]",
+    "username": "carol",
+    "isActive": true,
+    "roles": [
+      { "roleId": "role1", "roleName": "moderator" }
+    ],
+    "c_purchase_history": {
+      "c_recent_orders": [
+        { "orderId": "101"} ,
+        { "orderId": "102" } ,
+        { "orderId": "103"}
+      ]
+    }
+  }
+]);
+
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.15.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.15.query.sqlpp
new file mode 100644
index 0000000..7947916
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/complex-case/complex-case.15.query.sqlpp
@@ -0,0 +1,49 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+use test;
+
+UPDATE UserTypes2 AS u
+(UPDATE roles AS r at o
+SET r.roleName = {"a":"manager"}
+where o=0)
+set u.c_purchase_history.c_recent_orders={"a":33}
+WHERE u.userId= 3;
+
+
+UPDATE UserTypes2 AS u
+(UPDATE roles AS r
+SET r.roleName = {"a":"manager"})
+set u.c_purchase_history.c_recent_orders={"a":33}
+set u.isActive=missing
+set u.username=null
+WHERE u.userId= 4;
+
+
+
+UPDATE UserTypes2 AS u
+set u.c_purchase_history.c_recent_orders={"a":null}
+set u.isActive=missing
+set u.username=null
+WHERE u.userId= 5;
+
+
+
+select * from UserTypes2
+order by userId;
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/simple-case/simple-case.22.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/simple-case/simple-case.22.query.sqlpp
index b91d248..6e6eebe 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/simple-case/simple-case.22.query.sqlpp
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/update-statements/simple-case/simple-case.22.query.sqlpp
@@ -19,6 +19,16 @@

 Use test;

+upsert into UserTypes([{ "userId": 3, "email": "[email protected]", 
"username": "michaelb", "isActive": true, "u1": { "u2": null, "u3": 1 }, "age": 
"five", "occupation": 4 },
+{ "userId": 4, "email": "[email protected]", "username": "emilyd", 
"isActive": true, "u1": { "u2": null, "u3": 1 }, "age": 23.1 } ,
+ { "userId": 5, "email": "[email protected]", "username": "chrisj", 
"isActive": false, "u1": { "u2": null, "u3": 1 }, "age": "old" }
+,{ "userId": 6, "email": "[email protected]", "username": 
"patriciag", "isActive": true, "u1": { "u2": null, "u3": 1 }, "age": "45" },
+{ "userId": 7, "email": "[email protected]", "username": "lindam", 
"isActive": false, "u1": { "u2": null, "u3": 1 } },
+{ "userId": 8, "email": "[email protected]", "username": "robertl", 
"isActive": true, "u1": { "u2": null, "u3": 1 }, "age": 31 },
+ { "userId": 9, "email": "[email protected]", "username": "jamesw", 
"isActive": true, "u1": { "u2": null, "u3": 1 }, "age": "65"  },
+ { "userId": 10, "email": "[email protected]", "username": "marym", 
"isActive": false, "u1": { "u2": null, "u3": 1 }, "timeZone": "PT", "age": 32, 
"addresses": [ { "city": "Riverside", "zipcode": 92510 } ] } ,
+{ "userId": 11, "email": "[email protected]", "username": "jk", 
"isActive": true, "age": 31, "addresses": [{ "city": "Irvine, United States", 
"street": "Second st", "zipcode": 98128 }, { "city": "iii, United States", 
"street": "Second st", "zipcode": 9000 } ], "job": "pilot2", "u1": { "u2": 
null, "u3": 1, "u1": 1 }, "age2": null, "job3": null  }
+]);

 UPDATE UserTypes as u
  SET u.age=30
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/complex-case/complex-case.13.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/complex-case/complex-case.13.adm
new file mode 100644
index 0000000..3f72b2d
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/complex-case/complex-case.13.adm
@@ -0,0 +1,3 @@
+{ "UserTypes2": { "userId": 3, "c_purchase_history2": { "a2": 33 }, 
"c_purchase_history": { "a1": 33 }, "email": "[email protected]", "username": 
"carol", "isActive": true, "roles": [ { "roleId": "role1", "roleName": 
"moderator" } ] } }
+{ "UserTypes2": { "userId": 4, "a": "p", "c_purchase_history": { 
"c_recent_orders": [ "a", "5" ] }, "email": "[email protected]", "username": 
"carol", "roles": [ { "roleId": "role1", "roleName": "moderator" } ] } }
+{ "UserTypes2": { "userId": 5 } }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/complex-case/complex-case.15.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/complex-case/complex-case.15.adm
new file mode 100644
index 0000000..e782e99
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/complex-case/complex-case.15.adm
@@ -0,0 +1,3 @@
+{ "UserTypes2": { "userId": 3, "c_purchase_history": { "c_recent_orders": { 
"a": 33 } }, "roles": [ { "roleName": { "a": "manager" }, "roleId": "role1" }, 
{ "roleId": "role2", "roleName": "moderator" } ], "email": "[email protected]", 
"username": "carol", "isActive": true } }
+{ "UserTypes2": { "userId": 4, "username": null, "c_purchase_history": { 
"c_recent_orders": { "a": 33 } }, "roles": [ { "roleName": { "a": "manager" }, 
"roleId": "role1" } ], "email": "[email protected]" } }
+{ "UserTypes2": { "userId": 5, "username": null, "c_purchase_history": { 
"c_recent_orders": { "a": null } }, "email": "[email protected]", "roles": [ { 
"roleId": "role1", "roleName": "moderator" } ] } }
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.19.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.19.adm
index bce9ccb..232b330 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.19.adm
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.19.adm
@@ -1 +1 @@
-{ "userId": 11, "email": "[email protected]", "username": "jk", 
"isActive": true, "u1": { "u2": "3", "u1": 1 }, "age2": null, "job3": null, 
"age": null, "addresses": [ { "city": "Irvine, United States", "street": 
"Second st", "zipcode": 98128 } ] }
+{ "userId": 11, "email": "[email protected]", "username": "jk", 
"isActive": true, "age2": null, "job3": null, "age": null, "addresses": [ { 
"city": "Irvine, United States", "street": "Second st", "zipcode": 98128 } ] }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.20.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.20.adm
index 9d7f002..a964f80 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.20.adm
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.20.adm
@@ -1,11 +1,11 @@
-{ "UserTypes": { "userId": 1, "email": "[email protected]", "username": 
"johndoe", "isActive": true, "u1": { "u2": null, "u3": 1 }, "totaltax": 0.25, 
"totalcost": 25, "occupation": "teacher", "age": 23 } }
-{ "UserTypes": { "userId": 2, "email": "[email protected]", "username": 
"janesmith", "isActive": false, "u1": { "u2": null, "u3": 1 }, "occupation": 
"firefighter" } }
-{ "UserTypes": { "userId": 3, "email": "[email protected]", 
"username": "michaelb", "isActive": true, "u1": { "u2": null, "u3": 1 }, "age": 
"five", "occupation": 4 } }
-{ "UserTypes": { "userId": 4, "email": "[email protected]", "username": 
"emilyd", "isActive": true, "u1": { "u2": null, "u3": 1 }, "age": 23.1 } }
-{ "UserTypes": { "userId": 5, "email": "[email protected]", "username": 
"chrisj", "isActive": false, "u1": { "u2": null, "u3": 1 }, "age": "old" } }
-{ "UserTypes": { "userId": 6, "email": "[email protected]", 
"username": "patriciag", "isActive": true, "u1": { "u2": null, "u3": 1 }, 
"age": "45" } }
-{ "UserTypes": { "userId": 7, "email": "[email protected]", 
"username": "lindam", "isActive": false, "u1": { "u2": null, "u3": 1 } } }
-{ "UserTypes": { "userId": 8, "email": "[email protected]", "username": 
"robertl", "isActive": true, "u1": { "u2": null, "u3": 1 }, "age": 31 } }
-{ "UserTypes": { "userId": 9, "email": "[email protected]", "username": 
"jamesw", "isActive": true, "u1": { "u2": null, "u3": 1 }, "age": "65" } }
-{ "UserTypes": { "userId": 10, "email": "[email protected]", "username": 
"marym", "isActive": false, "u1": { "u2": null, "u3": 1 }, "timeZone": "PT", 
"age": 32, "addresses": [ { "city": "Riverside", "zipcode": 92510 } ] } }
-{ "UserTypes": { "userId": 11, "email": "[email protected]", "username": 
"jk", "isActive": true, "u1": { "u2": null, "u3": 1, "u1": 1 }, "age2": null, 
"job3": null, "age": null, "addresses": [ { "city": "Irvine, United States", 
"street": "Second st", "zipcode": 98128 } ] } }
+{ "UserTypes": { "userId": 1, "email": "[email protected]", "username": 
"johndoe", "isActive": true, "totaltax": 0.25, "totalcost": 25, "occupation": 
"teacher", "age": 23 } }
+{ "UserTypes": { "userId": 2, "email": "[email protected]", "username": 
"janesmith", "isActive": false, "occupation": "firefighter" } }
+{ "UserTypes": { "userId": 3, "email": "[email protected]", 
"username": "michaelb", "isActive": true, "age": "five", "occupation": 4 } }
+{ "UserTypes": { "userId": 4, "email": "[email protected]", "username": 
"emilyd", "isActive": true, "age": 23.1 } }
+{ "UserTypes": { "userId": 5, "email": "[email protected]", "username": 
"chrisj", "isActive": false, "age": "old" } }
+{ "UserTypes": { "userId": 6, "email": "[email protected]", 
"username": "patriciag", "isActive": true, "age": "45" } }
+{ "UserTypes": { "userId": 7, "email": "[email protected]", 
"username": "lindam", "isActive": false } }
+{ "UserTypes": { "userId": 8, "email": "[email protected]", "username": 
"robertl", "isActive": true, "age": 31 } }
+{ "UserTypes": { "userId": 9, "email": "[email protected]", "username": 
"jamesw", "isActive": true, "age": "65" } }
+{ "UserTypes": { "userId": 10, "email": "[email protected]", "username": 
"marym", "isActive": false, "timeZone": "PT", "age": 32, "addresses": [ { 
"city": "Riverside", "zipcode": 92510 } ] } }
+{ "UserTypes": { "userId": 11, "email": "[email protected]", "username": 
"jk", "isActive": true, "age2": null, "job3": null, "age": null, "addresses": [ 
{ "city": "Irvine, United States", "street": "Second st", "zipcode": 98128 } ] 
} }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.21.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.21.adm
index a54c923..506ca2a 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.21.adm
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.21.adm
@@ -1 +1 @@
-{ "userId": 11, "email": "[email protected]", "username": "jk", 
"isActive": true, "job": "pilot2", "age": 31, "addresses": [ { "city": "Irvine, 
United States", "street": "Second st", "zipcode": 98128 }, { "city": "iii, 
United States", "street": "Second st", "zipcode": 9000 } ], "u1": { "u2": null, 
"u3": 1, "u1": 1 }, "age2": null, "job3": null }
+{ "userId": 11, "email": "[email protected]", "username": "jk", 
"isActive": true, "job": "pilot2", "age": 31, "addresses": [ { "city": "Irvine, 
United States", "street": "Second st", "zipcode": 98128 }, { "city": "iii, 
United States", "street": "Second st", "zipcode": 9000 } ], "age2": null, 
"job3": null }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.23.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.23.adm
index 53c9081..d929b58 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.23.adm
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/update-statements/simple-case/simple-case.23.adm
@@ -1,5 +1,5 @@
-{ "UserTypes": { "userId": 1, "email": "[email protected]", "username": 
"johndoe", "isActive": true, "u1": { "u2": null, "u3": 1 }, "totaltax": 0.25, 
"totalcost": 25, "occupation": "teacher", "age": 23 } }
-{ "UserTypes": { "userId": 2, "email": "[email protected]", "username": 
"janesmith", "isActive": false, "u1": { "u2": null, "u3": 1 }, "occupation": 
"firefighter" } }
+{ "UserTypes": { "userId": 1, "email": "[email protected]", "username": 
"johndoe", "isActive": true, "totaltax": 0.25, "totalcost": 25, "occupation": 
"teacher", "age": 23 } }
+{ "UserTypes": { "userId": 2, "email": "[email protected]", "username": 
"janesmith", "isActive": false, "occupation": "firefighter" } }
 { "UserTypes": { "userId": 3, "email": "[email protected]", 
"username": "michaelb", "isActive": true, "u1": { "u2": null, "u3": 1 }, "age": 
"five", "occupation": 4 } }
 { "UserTypes": { "userId": 4, "email": "[email protected]", "username": 
"emilyd", "isActive": true, "u1": { "u2": null, "u3": 1 }, "age": 23.1 } }
 { "UserTypes": { "userId": 5, "email": "[email protected]", "username": 
"chrisj", "isActive": false, "u1": { "u2": null, "u3": 1 }, "age": "old" } }
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/ChangeExpression.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/ChangeExpression.java
index 39b6a44..ac38e8d 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/ChangeExpression.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/ChangeExpression.java
@@ -244,6 +244,10 @@
         dataRemovalRecord = result.second;
     }

+    public boolean assignsWholeRecord() {
+        return exprTree.assignsWholeRecord();
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(pathExprs, valueExprs, dataTransformRecord, 
dataRemovalRecord, exprTree, priorExpr,
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SetExpressionTree.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SetExpressionTree.java
index fe2031f..69c076a 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SetExpressionTree.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SetExpressionTree.java
@@ -20,18 +20,24 @@
 package org.apache.asterix.lang.sqlpp.parser;

 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;

 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.functions.FunctionSignature;
 import org.apache.asterix.lang.common.base.Expression;
 import org.apache.asterix.lang.common.base.Literal;
+import org.apache.asterix.lang.common.expression.CallExpr;
 import org.apache.asterix.lang.common.expression.FieldAccessor;
 import org.apache.asterix.lang.common.expression.FieldBinding;
 import org.apache.asterix.lang.common.expression.LiteralExpr;
 import org.apache.asterix.lang.common.expression.RecordConstructor;
 import org.apache.asterix.lang.common.literal.NullLiteral;
 import org.apache.asterix.lang.common.literal.StringLiteral;
+import org.apache.asterix.lang.common.literal.TrueLiteral;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
+import org.apache.asterix.om.functions.BuiltinFunctions;
 import org.apache.hyracks.algebricks.common.utils.Pair;

 /**
@@ -74,7 +80,7 @@
     private final Node root;

     public SetExpressionTree() {
-        root = new Node("init", null);
+        root = new Node("init", null, true);
     }

     public void insertPath(Expression path, Expression valueExpr) throws 
CompilationException {
@@ -102,6 +108,11 @@
         return createRecordConstructorInner(root);
     }

+    /** Used by UPDATE rewrite: {@code SET u = expr} replaces the row with 
{@code expr}. */
+    public boolean assignsWholeRecord() {
+        return root.hasExpression() && !root.hasChildren();
+    }
+
     private Node accessOrCreatePath(FieldAccessor path, Node node) throws 
CompilationException {
         Expression leadingExpr = path.getExpr();

@@ -111,13 +122,21 @@
         if (node.hasExpression()) {
             throw new 
CompilationException(ErrorCode.UPDATE_ATTEMPT_ON_CONFLICTING_PATHS, 
path.getSourceLocation());
         }
-        return node.retrieveChild(path.getIdent().getValue());
+        Node child = node.retrieveChild(path.getIdent().getValue());
+        // Save the path on first visit; the runtime is-object guard for 
deep-path SETs needs it.
+        child.pathExpr = path;
+        return child;
     }

     private Pair<Expression, Expression> createRecordConstructorInner(Node 
node) {
         if (node.hasExpression()) {
             Expression expr = node.getExpression();
             if (expr.getKind() != Expression.Kind.LITERAL_EXPRESSION) {
+                // SET p.f = {...}: also emit a deletion entry so the old 
value is removed
+                // before the new record is written (full replace, not merge).
+                if (replaceWholeFieldWithObject(node, expr)) {
+                    return new Pair<>(expr, new 
LiteralExpr(NullLiteral.INSTANCE));
+                }
                 return new Pair<>(expr, null);
             }
             LiteralExpr literalExpr = (LiteralExpr) expr;
@@ -143,17 +162,50 @@
         Expression setRecord = setRecordArgs.isEmpty() ? null : new 
RecordConstructor(setRecordArgs, true);
         Expression deletionRecord =
                 deletionRecordArgs.isEmpty() ? null : new 
RecordConstructor(deletionRecordArgs, true);
+        // Deep-path SET only (e.g. SET p.a.b = X): wrap the overlay in
+        //   CASE WHEN is-object(prefix) THEN overlay ELSE prefix
+        // so that when the prefix isn't a record at runtime, the merge sees 
the same value on
+        // both sides and leaves the field untouched.
+        if (setRecord != null && !node.isRoot && node.pathExpr != null) {
+            Expression prefix = node.pathExpr;
+            CallExpr isObject =
+                    new CallExpr(new 
FunctionSignature(BuiltinFunctions.IS_OBJECT), 
Collections.singletonList(prefix));
+            isObject.setSourceLocation(prefix.getSourceLocation());
+            CaseExpression guarded =
+                    new CaseExpression(isObject, Collections.singletonList(new 
LiteralExpr(TrueLiteral.INSTANCE)),
+                            Collections.singletonList(setRecord), prefix);
+            guarded.setSourceLocation(prefix.getSourceLocation());
+            setRecord = guarded;
+        }
         return new Pair<>(setRecord, deletionRecord);
     }

+    /** True only for "whole-field" record assignments: SET alias.f = {...}. */
+    private static boolean replaceWholeFieldWithObject(Node node, Expression 
expr) {
+        if (node.isRoot || node.hasChildren()) {
+            return false;
+        }
+        if (expr.getKind() != Expression.Kind.RECORD_CONSTRUCTOR_EXPRESSION) {
+            return false;
+        }
+        if (node.pathExpr == null || node.pathExpr.getKind() != 
Expression.Kind.FIELD_ACCESSOR_EXPRESSION) {
+            return false;
+        }
+        Expression lead = ((FieldAccessor) node.pathExpr).getExpr();
+        return lead.getKind() == Expression.Kind.VARIABLE_EXPRESSION;
+    }
+
     private static class Node {
         private final String name;
         private Expression expr;
+        private Expression pathExpr;
         List<Node> children;
+        private final boolean isRoot;

-        private Node(String name, Expression expr) {
+        private Node(String name, Expression expr, boolean isRoot) {
             this.name = name;
             this.expr = expr;
+            this.isRoot = isRoot;
             children = new ArrayList<>();
         }

@@ -180,7 +232,7 @@
                 }
             }
             // If not found and createIfEmpty is true, create and add the 
child node
-            Node newChild = new Node(childName, null); // New child node with 
no expression
+            Node newChild = new Node(childName, null, false); // New child 
node with no expression
             children.add(newChild);
             return newChild;
         }
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppChangeExprToSelectExprVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppChangeExprToSelectExprVisitor.java
index 80263b9..a2ab7ad 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppChangeExprToSelectExprVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppChangeExprToSelectExprVisitor.java
@@ -206,7 +206,9 @@
             dataTransformRecord = 
substituteVariableInExpression(dataTransformRecord, originalVarName,
                     currentContextVariable, changeExpr);
             changeExpr.setPriorExpr(projectExpr);
-            if (dataTransformRecord.getKind() == 
Expression.Kind.RECORD_CONSTRUCTOR_EXPRESSION) {
+            if (changeExpr.assignsWholeRecord()) {
+                projectExpr = dataTransformRecord;
+            } else if (dataTransformRecord.getKind() == 
Expression.Kind.RECORD_CONSTRUCTOR_EXPRESSION) {
                 projectExpr = new CallExpr(new 
FunctionSignature(BuiltinFunctions.RECORD_TRANSFORM),
                         new ArrayList<>(Arrays.asList(dataTransformRecord, 
projectExpr)));
                 ((CallExpr) 
projectExpr).setSourceLocation(rewrittenFirstExpr.getSourceLocation());

--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21205?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://asterix-gerrit.ics.uci.edu/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: asterixdb
Gerrit-Branch: lumina
Gerrit-Change-Id: I07a2fc3c76afe1f26d95225e4010b57f662f5ef0
Gerrit-Change-Number: 21205
Gerrit-PatchSet: 18
Gerrit-Owner: Shahrzad Shirazi <[email protected]>
Gerrit-Reviewer: Ali Alsuliman <[email protected]>
Gerrit-Reviewer: Anon. E. Moose #1000171
Gerrit-Reviewer: Jenkins <[email protected]>
Gerrit-Reviewer: Shahrzad Shirazi <[email protected]>

Reply via email to