You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@asterixdb.apache.org by AsterixDB Code Review <do...@asterix-gerrit.ics.uci.edu> on 2026/07/13 22:02:00 UTC

[L] Change in asterixdb[trinity]: fixes for obj_put

From Shahrzad Shirazi <sh...@ucr.edu>:

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


Change subject: fixes for obj_put
......................................................................

fixes for obj_put

Change-Id: Ibab57b815d726e1ed8874fb9ef78dff850244169
---
M asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/ObjectsQueries.xml
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.1.ddl.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.2.update.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.3.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_put.4.ddl.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_put/object_put.8.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_mod/object_mod.3.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_put/object_put.8.adm
M asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AbstractRecordFunctionTypeComputer.java
M asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddTypeComputer.java
M asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordPutTypeComputer.java
M asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordRemoveTypeComputer.java
M asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordRenameTypeComputer.java
M asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordPutEvaluator.java
14 files changed, 226 insertions(+), 35 deletions(-)



  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb refs/changes/24/21424/1

diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/ObjectsQueries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/ObjectsQueries.xml
index 77fc7c5..4150d11 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/ObjectsQueries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/ObjectsQueries.xml
@@ -141,6 +141,11 @@
     </compilation-unit>
   </test-case>
   <test-case FilePath="objects">
+    <compilation-unit name="object_mod">
+      <output-dir compare="Text">object_mod</output-dir>
+    </compilation-unit>
+  </test-case>
+  <test-case FilePath="objects">
     <compilation-unit name="object_names">
       <output-dir compare="Text">object_names</output-dir>
     </compilation-unit>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.1.ddl.sqlpp
new file mode 100644
index 0000000..771c9d0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.1.ddl.sqlpp
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description  : Testing object_put/add with values being added to open and closed parts of the record.
+ * Expected Res : Success
+ */
+
+DROP DATAVERSE TestDataverse IF EXISTS;
+CREATE DATAVERSE TestDataverse;
+
+USE TestDataverse;
+
+CREATE TYPE TestDataverse.TestType AS {
+  id: int,
+  closed_int_field: int,
+  closed_str_field: string
+};
+
+CREATE DATASET TestDataverse.TestDataset(TestDataverse.TestType) PRIMARY KEY id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.2.update.sqlpp
new file mode 100644
index 0000000..0477ece
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.2.update.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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 TestDataverse;
+INSERT INTO TestDataset([
+{ "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def" }
+]
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.3.query.sqlpp
new file mode 100644
index 0000000..c286c7f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_mod.3.query.sqlpp
@@ -0,0 +1,53 @@
+/*
+ * 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 TestDataverse;
+
+SELECT
+OBJECT_PUT(t, "from_closed_int_field", t.closed_int_field) AS put_from_closed_int_field,
+OBJECT_PUT(t, "from_closed_str_field", t.closed_str_field) AS put_from_closed_str_field,
+OBJECT_PUT(t, "from_open_int_field", t.open_int_field) AS put_from_open_int_field,
+OBJECT_PUT(t, "from_open_str_field", t.open_str_field) AS put_from_open_str_field,
+
+OBJECT_PUT(t, "closed_int_field", t.closed_str_field) AS put_from_closed_str_field_to_closed_int_field,
+OBJECT_PUT(t, "closed_str_field", t.closed_int_field) AS put_from_closed_int_field_to_closed_str_field,
+OBJECT_PUT(t, "open_int_field", t.open_str_field) AS put_from_open_str_field_to_open_int_field,
+OBJECT_PUT(t, "open_str_field", t.open_int_field) AS put_from_open_int_field_to_open_str_field,
+
+OBJECT_PUT(t, "closed_int_field", t.open_int_field) AS put_from_open_int_field_to_closed_int_field,
+OBJECT_PUT(t, "closed_str_field", t.open_str_field) AS put_from_open_str_field_to_closed_str_field,
+OBJECT_PUT(t, "open_int_field", t.closed_int_field) AS put_from_closed_int_field_to_open_int_field,
+OBJECT_PUT(t, "open_str_field", t.closed_str_field) AS put_from_closed_str_field_to_open_str_field,
+
+OBJECT_ADD(t, "from_closed_int_field", t.closed_int_field) AS add_from_closed_int_field,
+OBJECT_ADD(t, "from_closed_str_field", t.closed_str_field) AS add_from_closed_str_field,
+OBJECT_ADD(t, "from_open_int_field", t.open_int_field) AS add_from_open_int_field,
+OBJECT_ADD(t, "from_open_str_field", t.open_str_field) AS add_from_open_str_field,
+
+OBJECT_ADD(t, "closed_int_field", t.closed_str_field) AS add_from_closed_str_field_to_closed_int_field,
+OBJECT_ADD(t, "closed_str_field", t.closed_int_field) AS add_from_closed_int_field_to_closed_str_field,
+OBJECT_ADD(t, "open_int_field", t.open_str_field) AS add_from_open_str_field_to_open_int_field,
+OBJECT_ADD(t, "open_str_field", t.open_int_field) AS add_from_open_int_field_to_open_str_field,
+
+OBJECT_ADD(t, "closed_int_field", t.open_int_field) AS add_from_open_int_field_to_closed_int_field,
+OBJECT_ADD(t, "closed_str_field", t.open_str_field) AS add_from_open_str_field_to_closed_str_field,
+OBJECT_ADD(t, "open_int_field", t.closed_int_field) AS add_from_closed_int_field_to_open_int_field,
+OBJECT_ADD(t, "open_str_field", t.closed_str_field) AS add_from_closed_str_field_to_open_str_field
+
+FROM TestDataset AS t;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_put.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_put.4.ddl.sqlpp
new file mode 100644
index 0000000..bd8b62c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_mod/object_put.4.ddl.sqlpp
@@ -0,0 +1,20 @@
+/*
+ * 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 TestDataverse IF EXISTS;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_put/object_put.8.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_put/object_put.8.query.sqlpp
new file mode 100644
index 0000000..a606506
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_put/object_put.8.query.sqlpp
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description  : Testing object_put under different queries.
+ * Expected Res : Success
+ */
+
+use TestDataverse;
+
+
+SELECT  VALUE {
+
+  "t1c":  object_put({"a": 1, "b": 2}, "a", missing),
+  "t2c":  object_put({"a": 1, "b": 2}, "a", 3),
+  "t3c":  object_put({"a": 1, "b": 2}, "b", 3),
+  "t4c":  object_put({"a": 1, "b": 2}, "d", 3),
+  "t5c":  object_put({"a": 1, "b": 2, "c": 7}, "b", 3)
+};
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_mod/object_mod.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_mod/object_mod.3.adm
new file mode 100644
index 0000000..6f4b590
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_mod/object_mod.3.adm
@@ -0,0 +1 @@
+{ "put_from_closed_int_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "from_closed_int_field": 10, "open_int_field": 100, "open_str_field": "def" }, "put_from_closed_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "from_closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def" }, "put_from_open_int_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def", "from_open_int_field": 100 }, "put_from_open_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def", "from_open_str_field": "def" }, "put_from_closed_str_field_to_closed_int_field": { "id": 1, "closed_int_field": "abc", "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def" }, "put_from_closed_int_field_to_closed_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": 10, "open_int_field": 100, "open_str_field": "def" }, "put_from_open_str_field_to_open_int_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": "def", "open_str_field": "def" }, "put_from_open_int_field_to_open_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": 100 }, "put_from_open_int_field_to_closed_int_field": { "id": 1, "closed_str_field": "abc", "closed_int_field": 100, "open_int_field": 100, "open_str_field": "def" }, "put_from_open_str_field_to_closed_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "def", "open_int_field": 100, "open_str_field": "def" }, "put_from_closed_int_field_to_open_int_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 10, "open_str_field": "def" }, "put_from_closed_str_field_to_open_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_str_field": "abc", "open_int_field": 100 }, "add_from_closed_int_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "from_closed_int_field": 10, "open_int_field": 100, "open_str_field": "def" }, "add_from_closed_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "from_closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def" }, "add_from_open_int_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def", "from_open_int_field": 100 }, "add_from_open_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def", "from_open_str_field": "def" }, "add_from_closed_str_field_to_closed_int_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def" }, "add_from_closed_int_field_to_closed_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def" }, "add_from_open_str_field_to_open_int_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def" }, "add_from_open_int_field_to_open_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def" }, "add_from_open_int_field_to_closed_int_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def" }, "add_from_open_str_field_to_closed_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def" }, "add_from_closed_int_field_to_open_int_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_int_field": 100, "open_str_field": "def" }, "add_from_closed_str_field_to_open_str_field": { "id": 1, "closed_int_field": 10, "closed_str_field": "abc", "open_str_field": "def", "open_int_field": 100 } }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_put/object_put.8.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_put/object_put.8.adm
new file mode 100644
index 0000000..9872250
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_put/object_put.8.adm
@@ -0,0 +1 @@
+{ "t1c": { "b": 2 }, "t2c": { "a": 3, "b": 2 }, "t3c": { "a": 1, "b": 3 }, "t4c": { "a": 1, "b": 2, "d": 3 }, "t5c": { "a": 1, "b": 3, "c": 7 } }
\ No newline at end of file
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AbstractRecordFunctionTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AbstractRecordFunctionTypeComputer.java
index 580cab4..371d69e 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AbstractRecordFunctionTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AbstractRecordFunctionTypeComputer.java
@@ -82,11 +82,11 @@
         isOutputNullable |= TypeHelper.canBeNull(type1);
 
         // Compute our type.
-        return computeTypeImpl(functionCallExpression, env, inputRecordType, isOutputMissable, isOutputNullable);
+        return computeTypeImpl(functionCallExpression, type0, env, inputRecordType, isOutputMissable, isOutputNullable);
     }
 
     protected abstract IAType computeTypeImpl(AbstractFunctionCallExpression functionCallExpression,
-            IVariableTypeEnvironment env, ARecordType inputRecordType, boolean isOutputMissable,
+            IAType arg0InRecType, IVariableTypeEnvironment env, ARecordType inputRecordType, boolean isOutputMissable,
             boolean isOutputNullable) throws AlgebricksException;
 
     protected static IAType wrapTypeWithUnknown(IAType originalType, boolean isMissable, boolean isNullable) {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddTypeComputer.java
index 4815340..fd874a5 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddTypeComputer.java
@@ -40,17 +40,16 @@
     }
 
     @Override
-    public IAType computeTypeImpl(AbstractFunctionCallExpression functionCallExpression, IVariableTypeEnvironment env,
-            ARecordType inputRecordType, boolean isOutputMissable, boolean isOutputNullable)
-            throws AlgebricksException {
+    public IAType computeTypeImpl(AbstractFunctionCallExpression functionCallExpression, IAType arg0InRecType,
+            IVariableTypeEnvironment env, ARecordType inputRecordType, boolean isOutputMissable,
+            boolean isOutputNullable) throws AlgebricksException {
         // If our third argument is missing, then just return the type of our first argument.
         ILogicalExpression arg2 = functionCallExpression.getArguments().get(2).getValue();
         IAType type2 = (IAType) env.getType(arg2);
         IAType actualType2 = TypeComputeUtils.getActualType(type2);
         ATypeTag tag2 = actualType2.getTypeTag();
         if (tag2 == ATypeTag.MISSING) {
-            IAType type0 = (IAType) env.getType(functionCallExpression.getArguments().get(0).getValue());
-            return wrapTypeWithUnknown(type0, isOutputMissable, isOutputNullable);
+            return wrapTypeWithUnknown(arg0InRecType, isOutputMissable, isOutputNullable);
         }
 
         // We expect a constant for our second argument.
@@ -66,18 +65,23 @@
         // If our field is found, return the original record type. Otherwise, add our new field.
         ARecordType outputRecordType = inputRecordType;
         if (!Arrays.asList(inputRecordType.getFieldNames()).contains(newFieldName)) {
-            String[] fieldNames = new String[inputRecordType.getFieldNames().length + 1];
-            IAType[] fieldTypes = new IAType[inputRecordType.getFieldTypes().length + 1];
-            int currentCursorPosition = 0;
-            for (; currentCursorPosition < inputRecordType.getFieldNames().length; currentCursorPosition++) {
-                fieldNames[currentCursorPosition] = inputRecordType.getFieldNames()[currentCursorPosition];
-                fieldTypes[currentCursorPosition] = inputRecordType.getFieldTypes()[currentCursorPosition];
-            }
-            fieldNames[currentCursorPosition] = newFieldName;
-            fieldTypes[currentCursorPosition] = type2;
             String inputTypeName = inputRecordType.getTypeName();
             String outputTypeName = inputTypeName != null ? inputTypeName + "_add_" + newFieldName : null;
-            outputRecordType = new ARecordType(outputTypeName, fieldNames, fieldTypes, inputRecordType.isOpen());
+            if (actualType2.getTypeTag() == ATypeTag.ANY) {
+                outputRecordType = new ARecordType(outputTypeName, inputRecordType.getFieldNames(),
+                        inputRecordType.getFieldTypes(), true);
+            } else {
+                String[] fieldNames = new String[inputRecordType.getFieldNames().length + 1];
+                IAType[] fieldTypes = new IAType[inputRecordType.getFieldTypes().length + 1];
+                int currentCursorPosition = 0;
+                for (; currentCursorPosition < inputRecordType.getFieldNames().length; currentCursorPosition++) {
+                    fieldNames[currentCursorPosition] = inputRecordType.getFieldNames()[currentCursorPosition];
+                    fieldTypes[currentCursorPosition] = inputRecordType.getFieldTypes()[currentCursorPosition];
+                }
+                fieldNames[currentCursorPosition] = newFieldName;
+                fieldTypes[currentCursorPosition] = type2;
+                outputRecordType = new ARecordType(outputTypeName, fieldNames, fieldTypes, inputRecordType.isOpen());
+            }
         }
         return wrapTypeWithUnknown(outputRecordType, isOutputMissable, isOutputNullable);
     }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordPutTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordPutTypeComputer.java
index a92907d..fe32770 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordPutTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordPutTypeComputer.java
@@ -41,9 +41,9 @@
     }
 
     @Override
-    public IAType computeTypeImpl(AbstractFunctionCallExpression functionCallExpression, IVariableTypeEnvironment env,
-            ARecordType inputRecordType, boolean isOutputMissable, boolean isOutputNullable)
-            throws AlgebricksException {
+    public IAType computeTypeImpl(AbstractFunctionCallExpression functionCallExpression, IAType arg0InRecType,
+            IVariableTypeEnvironment env, ARecordType inputRecordType, boolean isOutputMissable,
+            boolean isOutputNullable) throws AlgebricksException {
         // Extract the type of our third argument. If it is MISSING, then we are performing a field removal.
         ILogicalExpression arg2 = functionCallExpression.getArguments().get(2).getValue();
         IAType type2 = (IAType) env.getType(arg2);
@@ -62,6 +62,7 @@
 
         // Remove or replace our field name and type (dependent on the type of our third argument).
         boolean fieldFound = false;
+        boolean makeOpen = false;
         List<String> outputFieldNames = new ArrayList<>();
         List<IAType> outputFieldTypes = new ArrayList<>();
         for (int i = 0; i < inputRecordType.getFieldNames().length; i++) {
@@ -70,10 +71,15 @@
             if (!inputFieldName.equals(newFieldName)) {
                 outputFieldNames.add(inputFieldName);
                 outputFieldTypes.add(inputFieldType);
-
             } else {
                 fieldFound = true;
-                if (!isFieldRemoval) {
+                // we cannot add a field to the record type (schema) if it is ANY. fields that are part of the record
+                // type need to have a known type so that the proper (non-tagged) SerializerDeserializer can be used
+                // fields with ANY need to go to the open part of the record type, and we need to make the record type
+                // open if it is not already
+                if (actualType2.getTypeTag() == ATypeTag.ANY) {
+                    makeOpen = true;
+                } else if (!isFieldRemoval) {
                     // Replace our input field type.
                     outputFieldNames.add(inputFieldName);
                     outputFieldTypes.add(type2);
@@ -94,14 +100,18 @@
             // We have replaced our argument field.
             String outputTypeName = doesRecordHaveTypeName ? inputTypeName + "_replaced_" + newFieldName : null;
             outputRecordType = new ARecordType(outputTypeName, outputFieldNames.toArray(String[]::new),
-                    outputFieldTypes.toArray(IAType[]::new), inputRecordType.isOpen());
+                    outputFieldTypes.toArray(IAType[]::new), inputRecordType.isOpen() || makeOpen);
         } else if (!isFieldRemoval) { // && !wasFieldFound
-            // We need to insert our argument field.
-            outputFieldNames.add(newFieldName);
-            outputFieldTypes.add(type2);
+            if (actualType2.getTypeTag() != ATypeTag.ANY) {
+                // We need to insert our argument field.
+                outputFieldNames.add(newFieldName);
+                outputFieldTypes.add(type2);
+            } else {
+                makeOpen = true;
+            }
             String outputTypeName = doesRecordHaveTypeName ? inputTypeName + "_add_" + newFieldName : null;
             outputRecordType = new ARecordType(outputTypeName, outputFieldNames.toArray(String[]::new),
-                    outputFieldTypes.toArray(IAType[]::new), inputRecordType.isOpen());
+                    outputFieldTypes.toArray(IAType[]::new), inputRecordType.isOpen() || makeOpen);
         } else { // isFieldRemoval && !wasFieldFound
             // We have not found the field to remove.
             outputRecordType = inputRecordType;
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordRemoveTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordRemoveTypeComputer.java
index c447e65..f9a7208 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordRemoveTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordRemoveTypeComputer.java
@@ -38,8 +38,9 @@
     }
 
     @Override
-    public IAType computeTypeImpl(AbstractFunctionCallExpression functionCallExpression, IVariableTypeEnvironment env,
-            ARecordType inputRecordType, boolean isOutputMissable, boolean isOutputNullable) {
+    public IAType computeTypeImpl(AbstractFunctionCallExpression functionCallExpression, IAType arg0InRecType,
+            IVariableTypeEnvironment env, ARecordType inputRecordType, boolean isOutputMissable,
+            boolean isOutputNullable) {
         // We expect a CONSTANT expression. Otherwise, defer the removal to runtime.
         ILogicalExpression arg1 = functionCallExpression.getArguments().get(1).getValue();
         if (arg1.getExpressionTag() != LogicalExpressionTag.CONSTANT) {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordRenameTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordRenameTypeComputer.java
index 4302082..7d80a27 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordRenameTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordRenameTypeComputer.java
@@ -45,9 +45,9 @@
     }
 
     @Override
-    public IAType computeTypeImpl(AbstractFunctionCallExpression functionCallExpression, IVariableTypeEnvironment env,
-            ARecordType inputRecordType, boolean isOutputMissable, boolean isOutputNullable)
-            throws AlgebricksException {
+    public IAType computeTypeImpl(AbstractFunctionCallExpression functionCallExpression, IAType arg0InRecType,
+            IVariableTypeEnvironment env, ARecordType inputRecordType, boolean isOutputMissable,
+            boolean isOutputNullable) throws AlgebricksException {
         // Our third argument should be of type "string".
         ILogicalExpression arg2 = functionCallExpression.getArguments().get(2).getValue();
         IAType type2 = (IAType) env.getType(arg2);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordPutEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordPutEvaluator.java
index 3a9f3f8..d5551c9 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordPutEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordPutEvaluator.java
@@ -44,13 +44,13 @@
         for (int i = 0, fieldCount = fieldNames.size(); i < fieldCount; i++) {
             final IVisitablePointable fieldName = fieldNames.get(i);
             final IVisitablePointable fieldValue = fieldValues.get(i);
-            if (!newFieldFound && !PointableHelper.isEqual(fieldName, newFieldNamePointable, stringBinaryComparator)) {
-                addField(fieldName, fieldValue);
-            } else {
+            if (PointableHelper.isEqual(fieldName, newFieldNamePointable, stringBinaryComparator)) {
                 newFieldFound = true;
                 if (!newFieldValueIsMissing) {
                     addField(newFieldNamePointable, newFieldValuePointable);
                 }
+            } else {
+                addField(fieldName, fieldValue);
             }
         }
         if (!newFieldFound) {

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

Gerrit-MessageType: newchange
Gerrit-Project: asterixdb
Gerrit-Branch: trinity
Gerrit-Change-Id: Ibab57b815d726e1ed8874fb9ef78dff850244169
Gerrit-Change-Number: 21424
Gerrit-PatchSet: 1
Gerrit-Owner: Shahrzad Shirazi <sh...@ucr.edu>