>From Ali Alsuliman <[email protected]>: Ali Alsuliman has submitted this change. ( https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/14404 )
Change subject: [NO ISSUE][FUN] extend object_concat to support an input array ...................................................................... [NO ISSUE][FUN] extend object_concat to support an input array - user model changes: no - storage format changes: no - interface changes: no Details: object_concat() should support an array of objects as a signle input. Change-Id: I2bf24229b5390106d06049c43af972734c6f9fd2 Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/14404 Integration-Tests: Jenkins <[email protected]> Tested-by: Jenkins <[email protected]> Reviewed-by: Ali Alsuliman <[email protected]> Reviewed-by: Dmitry Lychagin <[email protected]> --- 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_concat/object_concat.2.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat/object_concat.3.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.01.ddl.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.02.update.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.03.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.04.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.05.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.06.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.07.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.99.ddl.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat/object_concat.2.adm A asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat/object_concat.3.adm A asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.03.adm A asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.04.adm A asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.05.adm A asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.06.adm A asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.07.adm M asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/ListAccessor.java M asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatDescriptor.java M asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatEvalFactory.java M asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatStrictDescriptor.java M asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java 23 files changed, 493 insertions(+), 48 deletions(-) Approvals: Dmitry Lychagin: Looks good to me, approved Ali Alsuliman: Looks good to me, but someone else must approve Jenkins: Verified; Verified Anon. E. Moose #1000171: 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 bb51b39..2675c40 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 @@ -126,6 +126,11 @@ </compilation-unit> </test-case> <test-case FilePath="objects"> + <compilation-unit name="object_concat_with_array"> + <output-dir compare="Text">object_concat_with_array</output-dir> + </compilation-unit> + </test-case> + <test-case FilePath="objects"> <compilation-unit name="object_length"> <output-dir compare="Text">object_length</output-dir> </compilation-unit> diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat/object_concat.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat/object_concat.2.query.sqlpp new file mode 100644 index 0000000..775c79a --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat/object_concat.2.query.sqlpp @@ -0,0 +1,34 @@ +/* + * 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. + */ + +SELECT VALUE +[ + is_null(object_concat([])), + is_null(object_concat([null])), + is_missing(object_concat([missing])), + is_null(object_concat([{"a":1}, null])), + is_missing(object_concat([{"a":1}, null, missing])), + is_null(object_concat([{"a":1}, 1])), + is_null(object_concat([{"a":1}, []])), + object_concat([{"a":1, "b":"x"}]), + object_concat([{"a":1, "b":"x" }, {"c":true, "d":false}, {"e":null}] ), + object_concat([{"a":1, "b":"x", "c":true }, {"a":2, "b":"y" }, {"b":null}]), + object_concat([{"a":1, "b": { "x":2, "y":3 } }, {"a":10, "b": { "x":4, "y":5 } }, {"a":100}]), + object_concat([{"a":1, "b": { "x":2, "y":3 } }, {"a":10, "b": { "x":4, "y":5 } }, {"a":100, "b": { "x":400, "y":500 } }]) +] \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat/object_concat.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat/object_concat.3.query.sqlpp new file mode 100644 index 0000000..ddfa0d2 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat/object_concat.3.query.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. + */ + +SELECT VALUE +object_concat(( + SELECT VALUE object_add({}, i.id, i.label) + FROM [{"id":"test","label":"val"},{"id":"test2","label":"val1"}, {"id":"test2","label":"val2"}] i +)) \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.01.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.01.ddl.sqlpp new file mode 100644 index 0000000..26e1cf3 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.01.ddl.sqlpp @@ -0,0 +1,28 @@ +/* + * 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. + */ +// test that object_concat() accepts and processes a single list of records argument +DROP DATAVERSE test IF EXISTS; +CREATE DATAVERSE test; +USE test; + +CREATE TYPE flat_t AS {a: int, b: string}; +CREATE TYPE nesting_t AS {x: {a: int, b: string}, y: [flat_t]}; + +CREATE TYPE t1 AS {id: int, array_nesting_rec: [nesting_t], array_flat_rec: [flat_t]}; +CREATE DATASET ds(t1) PRIMARY KEY id; \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.02.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.02.update.sqlpp new file mode 100644 index 0000000..6051c9a --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.02.update.sqlpp @@ -0,0 +1,78 @@ +/* + * 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; + +INSERT INTO ds [ +{"id": 1 ,"array_nesting_rec": [{"x": {"a": 3, "b": "3"}, "y": [{"a": 3, "b": "3"}]}, + {"x": {"a": 2, "b": "2"}, "y": [{"a": 2, "b": "2"}]}, + {"x": {"a": 1, "b": "1"}, "y": [{"a": 1, "b": "1"}]}] + ,"array_flat_rec": [{"a": 3, "b": "3"}, + {"a": 2, "b": "2"}, + {"a": 1, "b": "1"}] + ,"optional_field1": [{"x": {"a": 3, "b": "3"}, "y": [{"a": 3, "b": "3"}]}, + {"x": {"a": 2, "b": "2"}, "y": [{"a": 2, "b": "2"}]}, + {"x": {"a": 1, "b": "1"}, "y": [{"a": 1, "b": "1"}]}] + ,"optional_field2": [{"a": 3, "b": "3"}, + {"a": 2, "b": "2"}, + {"a": 1, "b": "1"}] +}, +{"id": 2 ,"array_nesting_rec": [{"x": {"a": 3, "b": "3"}, "y": [{"a": 3, "b": "3"}]}, + {"x": {"a": 1, "b": "1"}, "y": [{"a": 1, "b": "1"}]}, + {"x": {"a": 2, "b": "2"}, "y": [{"a": 2, "b": "2"}]}] + ,"array_flat_rec": [{"a": 3, "b": "3"}, + {"a": 1, "b": "1"}, + {"a": 2, "b": "2"}] + ,"optional_field1": [{"x3": {"a": 3, "b": "3"}, "y3": [{"a": 3, "b": "3"}]}, + {"x1": {"a": 1, "b": "1"}, "y1": [{"a": 1, "b": "1"}]}, + {"x2": {"a": 2, "b": "2"}, "y2": [{"a": 2, "b": "2"}]}] + ,"optional_field2": [1, + {"a": 1, "b": "1"}, + "3"] +}, +{"id": 3 ,"array_nesting_rec": [{"x": {"a": 1, "b": "1"}, "y": [{"a": 1, "b": "1"}]}, + {"x": {"a": 2, "b": "2"}, "y": [{"a": 2, "b": "2"}]}, + {"x": {"a": 3, "b": "3"}, "y": [{"a": 3, "b": "3"}]}] + ,"array_flat_rec": [{"a": 1, "b": "1"}, + {"a": 2, "b": "2"}, + {"a": 3, "b": "3"}] + ,"optional_field1": 5 + ,"optional_field2": [{"x1": {"a": 1, "b": "1"}, "y1": [{"a": 1, "b": "1"}]}, + {"x2": {"a": 2, "b": "2"}, "y2": [{"a": 2, "b": "2"}]}, + {"x3": {"a": 3, "b": "3"}, "y3": [{"a": 3, "b": "3"}]}] +}, +{"id": 4 ,"array_nesting_rec": [{"x": {"a": 1, "b": "1"}, "y": [{"a": 1, "b": "1"}]}, + {"x": {"a": 2, "b": "2"}, "y": [{"a": 2, "b": "2"}]}, + {"x": {"a": 4, "b": "4"}, "y": [{"a": 4, "b": "4"}]}] + ,"array_flat_rec": [{"a": 1, "b": "1"}, + {"a": 2, "b": "2"}, + {"a": 4, "b": "4"}] + ,"optional_field1": {"x": {"a": 4, "b": "4"}, "y": [{"a": 4, "b": "4"}]} + ,"optional_field2": {"a": 4, "b": "4"} +}, +{"id": 5 ,"array_nesting_rec": [{"x": {"a": 1, "b": "1"}, "y": [{"a": 1, "b": "1"}]}, + {"x": {"a": 2, "b": "2"}, "y": [{"a": 2, "b": "2"}]}, + {"x": {"a": 5, "b": "5"}, "y": [{"a": 5, "b": "5"}]}] + ,"array_flat_rec": [{"a": 1, "b": "1"}, + {"a": 2, "b": "2"}, + {"a": 5, "b": "5"}] + ,"optional_field1": null + /*"optional_field2": missing*/ +} +]; \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.03.query.sqlpp new file mode 100644 index 0000000..89bc6f7 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.03.query.sqlpp @@ -0,0 +1,21 @@ +/* + * 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; + +FROM ds SELECT id, object_concat(array_nesting_rec) AS oc ORDER BY id; \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.04.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.04.query.sqlpp new file mode 100644 index 0000000..b877817 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.04.query.sqlpp @@ -0,0 +1,21 @@ +/* + * 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; + +FROM ds SELECT id, object_concat(array_flat_rec) AS oc ORDER BY id; \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.05.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.05.query.sqlpp new file mode 100644 index 0000000..b933712 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.05.query.sqlpp @@ -0,0 +1,21 @@ +/* + * 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; + +FROM ds SELECT id, object_concat(optional_field1) AS oc ORDER BY id; \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.06.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.06.query.sqlpp new file mode 100644 index 0000000..c5d5ab4 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.06.query.sqlpp @@ -0,0 +1,21 @@ +/* + * 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; + +FROM ds SELECT id, object_concat(optional_field2) AS oc ORDER BY id; \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.07.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.07.query.sqlpp new file mode 100644 index 0000000..5611a1d --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.07.query.sqlpp @@ -0,0 +1,21 @@ +/* + * 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; + +FROM ds SELECT id, object_concat(optional_field1, optional_field2) AS oc ORDER BY id; \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.99.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.99.ddl.sqlpp new file mode 100644 index 0000000..36b2bab --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/object_concat_with_array/object_concat_with_array.99.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 test IF EXISTS; \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat/object_concat.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat/object_concat.2.adm new file mode 100644 index 0000000..79d1707 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat/object_concat.2.adm @@ -0,0 +1 @@ +[ true, true, true, true, true, true, true, { "a": 1, "b": "x" }, { "e": null, "c": true, "d": false, "a": 1, "b": "x" }, { "b": null, "a": 2, "c": true }, { "a": 100, "b": { "x": 4, "y": 5 } }, { "a": 100, "b": { "x": 400, "y": 500 } } ] \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat/object_concat.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat/object_concat.3.adm new file mode 100644 index 0000000..237ea95 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat/object_concat.3.adm @@ -0,0 +1 @@ +{ "test2": "val2", "test": "val" } \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.03.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.03.adm new file mode 100644 index 0000000..15a0c1a --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.03.adm @@ -0,0 +1,5 @@ +{ "id": 1, "oc": { "x": { "a": 1, "b": "1" }, "y": [ { "a": 1, "b": "1" } ] } } +{ "id": 2, "oc": { "x": { "a": 2, "b": "2" }, "y": [ { "a": 2, "b": "2" } ] } } +{ "id": 3, "oc": { "x": { "a": 3, "b": "3" }, "y": [ { "a": 3, "b": "3" } ] } } +{ "id": 4, "oc": { "x": { "a": 4, "b": "4" }, "y": [ { "a": 4, "b": "4" } ] } } +{ "id": 5, "oc": { "x": { "a": 5, "b": "5" }, "y": [ { "a": 5, "b": "5" } ] } } \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.04.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.04.adm new file mode 100644 index 0000000..4eac053 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.04.adm @@ -0,0 +1,5 @@ +{ "id": 1, "oc": { "a": 1, "b": "1" } } +{ "id": 2, "oc": { "a": 2, "b": "2" } } +{ "id": 3, "oc": { "a": 3, "b": "3" } } +{ "id": 4, "oc": { "a": 4, "b": "4" } } +{ "id": 5, "oc": { "a": 5, "b": "5" } } \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.05.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.05.adm new file mode 100644 index 0000000..2f9609f --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.05.adm @@ -0,0 +1,5 @@ +{ "id": 1, "oc": { "x": { "a": 1, "b": "1" }, "y": [ { "a": 1, "b": "1" } ] } } +{ "id": 2, "oc": { "x2": { "a": 2, "b": "2" }, "y2": [ { "a": 2, "b": "2" } ], "x1": { "a": 1, "b": "1" }, "y1": [ { "a": 1, "b": "1" } ], "x3": { "a": 3, "b": "3" }, "y3": [ { "a": 3, "b": "3" } ] } } +{ "id": 3, "oc": null } +{ "id": 4, "oc": { "x": { "a": 4, "b": "4" }, "y": [ { "a": 4, "b": "4" } ] } } +{ "id": 5, "oc": null } diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.06.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.06.adm new file mode 100644 index 0000000..8decdbe --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.06.adm @@ -0,0 +1,5 @@ +{ "id": 1, "oc": { "a": 1, "b": "1" } } +{ "id": 2, "oc": null } +{ "id": 3, "oc": { "x3": { "a": 3, "b": "3" }, "y3": [ { "a": 3, "b": "3" } ], "x2": { "a": 2, "b": "2" }, "y2": [ { "a": 2, "b": "2" } ], "x1": { "a": 1, "b": "1" }, "y1": [ { "a": 1, "b": "1" } ] } } +{ "id": 4, "oc": { "a": 4, "b": "4" } } +{ "id": 5 } \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.07.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.07.adm new file mode 100644 index 0000000..b1f2107 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/object_concat_with_array/object_concat_with_array.07.adm @@ -0,0 +1,5 @@ +{ "id": 1, "oc": null } +{ "id": 2, "oc": null } +{ "id": 3, "oc": null } +{ "id": 4, "oc": { "a": 4, "b": "4", "x": { "a": 4, "b": "4" }, "y": [ { "a": 4, "b": "4" } ] } } +{ "id": 5 } \ No newline at end of file diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/ListAccessor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/ListAccessor.java index e834522..67d4808 100644 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/ListAccessor.java +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/ListAccessor.java @@ -98,6 +98,10 @@ } } + public ATypeTag getItemTypeAt(int itemIndex) throws HyracksDataException { + return getItemType(getItemOffset(itemIndex)); + } + public void writeItem(int itemIndex, DataOutput dos) throws IOException { int itemOffset = getItemOffset(itemIndex); int itemLength = getItemLength(itemOffset); diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatDescriptor.java index 401335c..b617085 100644 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatDescriptor.java +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatDescriptor.java @@ -46,18 +46,20 @@ } }; - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 2L; private ARecordType[] argTypes; + private ARecordType listItemRecordType; @Override public void setImmutableStates(Object... states) { - argTypes = (ARecordType[]) states; + argTypes = (ARecordType[]) states[0]; + listItemRecordType = (ARecordType) states[1]; } @Override public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) { - return new RecordConcatEvalFactory(args, argTypes, false, sourceLoc); + return new RecordConcatEvalFactory(args, argTypes, listItemRecordType, false, sourceLoc); } @Override diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatEvalFactory.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatEvalFactory.java index c4bc87e..bc1cacc 100644 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatEvalFactory.java +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatEvalFactory.java @@ -33,6 +33,7 @@ import org.apache.asterix.om.types.ARecordType; import org.apache.asterix.om.types.ATypeTag; import org.apache.asterix.om.types.IAType; +import org.apache.asterix.runtime.evaluators.common.ListAccessor; import org.apache.asterix.runtime.evaluators.functions.BinaryHashMap; import org.apache.asterix.runtime.exceptions.TypeMismatchException; import org.apache.hyracks.algebricks.common.utils.Triple; @@ -49,20 +50,23 @@ class RecordConcatEvalFactory implements IScalarEvaluatorFactory { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 2L; private final IScalarEvaluatorFactory[] args; private final ARecordType[] argTypes; + private final ARecordType listItemRecordType; + private final boolean failOnArgTypeMismatch; private final SourceLocation sourceLoc; - RecordConcatEvalFactory(IScalarEvaluatorFactory[] args, ARecordType[] argTypes, boolean failOnArgTypeMismatch, - SourceLocation sourceLoc) { + RecordConcatEvalFactory(IScalarEvaluatorFactory[] args, ARecordType[] argTypes, ARecordType listItemRecordType, + boolean failOnArgTypeMismatch, SourceLocation sourceLoc) { this.args = args; this.argTypes = argTypes; + this.listItemRecordType = listItemRecordType; this.failOnArgTypeMismatch = failOnArgTypeMismatch; this.sourceLoc = sourceLoc; } @@ -81,9 +85,16 @@ private static final int TABLE_FRAME_SIZE = 32768; private static final int TABLE_SIZE = 100; + private ListAccessor listAccessor; + private ARecordVisitablePointable itemRecordPointable; + private final ArrayBackedValueStorage itemRecordStorage; + private boolean itemRecordCastRequired; + + private ArgKind argKind; + private final IPointable firstArg; private final IScalarEvaluator[] argEvals; - private final IPointable[] argPointables; - private final ARecordVisitablePointable[] argRecordPointables; + private IPointable[] argPointables; + private ARecordVisitablePointable[] argRecordPointables; private final ARecordVisitablePointable openRecordPointable; private final BitSet castRequired; @@ -98,11 +109,12 @@ private final BinaryEntry keyEntry; private final BinaryEntry valEntry; + private int numRecords; + private RecordConcatEvaluator(IScalarEvaluator[] argEvals) { this.argEvals = argEvals; - argPointables = new IPointable[args.length]; - argRecordPointables = new ARecordVisitablePointable[args.length]; + firstArg = new VoidPointable(); openRecordPointable = new ARecordVisitablePointable(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE); resultStorage = new ArrayBackedValueStorage(); @@ -117,45 +129,101 @@ valEntry.set(new byte[0], 0, 0); castRequired = new BitSet(); - for (int i = 0; i < args.length; i++) { - argPointables[i] = new VoidPointable(); - ARecordType argType = argTypes[i]; - if (argType != null) { - argRecordPointables[i] = new ARecordVisitablePointable(argType); - if (hasDerivedType(argType.getFieldTypes())) { - castRequired.set(i); - if (castVisitor == null) { - castVisitor = new ACastVisitor(); - castVisitorArg = new Triple<>(openRecordPointable, openRecordPointable.getInputRecordType(), - Boolean.FALSE); + itemRecordStorage = new ArrayBackedValueStorage(); + if (listItemRecordType != null) { + // init if we know we will always get one list of records whose type is known at compile-time + itemRecordPointable = new ARecordVisitablePointable(listItemRecordType); + if (hasDerivedType(listItemRecordType.getFieldTypes())) { + itemRecordCastRequired = true; + initCastVisitor(); + } + } else { + // otherwise, any kind of arguments are possible (and possibly a single open list of records) + argPointables = new IPointable[args.length]; + argRecordPointables = new ARecordVisitablePointable[args.length]; + for (int i = 0; i < args.length; i++) { + argPointables[i] = new VoidPointable(); + ARecordType argType = argTypes[i]; + if (argType != null) { + argRecordPointables[i] = new ARecordVisitablePointable(argType); + if (hasDerivedType(argType.getFieldTypes())) { + castRequired.set(i); + initCastVisitor(); } } } } } + private void initCastVisitor() { + if (castVisitor == null) { + castVisitor = new ACastVisitor(); + castVisitorArg = + new Triple<>(openRecordPointable, openRecordPointable.getInputRecordType(), Boolean.FALSE); + } + } + @Override public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException { resultStorage.reset(); - if (validateArgs(tuple)) { - processArgs(); + if (args.length == 0) { + writeTypeTag(ATypeTag.SERIALIZED_NULL_TYPE_TAG, result); + return; } + if (!validateArgs(tuple, result)) { + return; + } + processArgs(); result.set(resultStorage); } - private boolean validateArgs(IFrameTupleReference tuple) throws HyracksDataException { - if (args.length == 0) { - writeTypeTag(ATypeTag.SERIALIZED_NULL_TYPE_TAG); - return false; + private boolean validateArgs(IFrameTupleReference tuple, IPointable result) throws HyracksDataException { + if (argEvals.length == 1) { + // either 1 list arg or 1 presumably record arg + argEvals[0].evaluate(tuple, firstArg); + byte[] data = firstArg.getByteArray(); + int offset = firstArg.getStartOffset(); + ATypeTag typeTag = ATypeTag.VALUE_TYPE_MAPPING[data[offset]]; + if (typeTag.isListType()) { + if (listAccessor == null) { + listAccessor = new ListAccessor(); + } + listAccessor.reset(data, offset); + argKind = ArgKind.SINGLE_ARG_LIST; + numRecords = listAccessor.size(); + if (numRecords == 0) { + writeTypeTag(ATypeTag.SERIALIZED_NULL_TYPE_TAG, result); + return false; + } + } else { + argKind = ArgKind.SINGLE_ARG; + numRecords = 1; + } + } else { + // fixed number of args (presumably records) + argKind = ArgKind.MULTIPLE_ARGS; + numRecords = argEvals.length; } - boolean returnMissing = false, returnNull = false; - for (int i = 0; i < argEvals.length; i++) { - IPointable argPtr = argPointables[i]; - argEvals[i].evaluate(tuple, argPtr); + return validateRecords(tuple, result, argKind); + } - byte[] data = argPtr.getByteArray(); - int offset = argPtr.getStartOffset(); - byte typeTag = data[offset]; + private boolean validateRecords(IFrameTupleReference tuple, IPointable result, ArgKind argKind) + throws HyracksDataException { + boolean returnMissing = false, returnNull = false; + for (int i = 0; i < numRecords; i++) { + byte typeTag; + if (argKind == ArgKind.SINGLE_ARG_LIST) { + typeTag = listAccessor.getItemTypeAt(i).serialize(); + } else if (argKind == ArgKind.SINGLE_ARG) { + // first arg has already been evaluated before + IPointable argPtr = argPointables[i]; + argPtr.set(firstArg); + typeTag = argPtr.getByteArray()[argPtr.getStartOffset()]; + } else { + IPointable argPtr = argPointables[i]; + argEvals[i].evaluate(tuple, argPtr); + typeTag = argPtr.getByteArray()[argPtr.getStartOffset()]; + } if (typeTag == ATypeTag.SERIALIZED_MISSING_TYPE_TAG) { returnMissing = true; @@ -174,11 +242,11 @@ } } if (returnMissing) { - writeTypeTag(ATypeTag.SERIALIZED_MISSING_TYPE_TAG); + writeTypeTag(ATypeTag.SERIALIZED_MISSING_TYPE_TAG, result); return false; } if (returnNull) { - writeTypeTag(ATypeTag.SERIALIZED_NULL_TYPE_TAG); + writeTypeTag(ATypeTag.SERIALIZED_NULL_TYPE_TAG, result); return false; } return true; @@ -187,14 +255,34 @@ private void processArgs() throws HyracksDataException { outRecordBuilder.init(); fieldMap.clear(); - for (int i = argEvals.length - 1; i >= 0; i--) { + if (argKind == ArgKind.SINGLE_ARG_LIST) { + processListRecords(); + } else { + processArgsRecords(); + } + outRecordBuilder.write(resultOutput, true); + } + + private void processListRecords() throws HyracksDataException { + for (int i = numRecords - 1; i >= 0; i--) { + try { + itemRecordStorage.reset(); + listAccessor.writeItem(i, itemRecordStorage.getDataOutput()); + appendRecord(itemRecordStorage, itemRecordPointable, itemRecordCastRequired); + } catch (IOException e) { + throw HyracksDataException.create(e); + } + } + } + + private void processArgsRecords() throws HyracksDataException { + for (int i = numRecords - 1; i >= 0; i--) { try { appendRecord(argPointables[i], argRecordPointables[i], castRequired.get(i)); } catch (IOException e) { throw HyracksDataException.create(e); } } - outRecordBuilder.write(resultOutput, true); } private void appendRecord(IPointable recordPtr, ARecordVisitablePointable argVisitablePointable, @@ -239,12 +327,19 @@ return false; } - private void writeTypeTag(byte typeTag) throws HyracksDataException { + private void writeTypeTag(byte typeTag, IPointable result) throws HyracksDataException { try { resultOutput.writeByte(typeTag); + result.set(resultStorage); } catch (IOException e) { throw HyracksDataException.create(e); } } } + + private enum ArgKind { + SINGLE_ARG_LIST, + SINGLE_ARG, + MULTIPLE_ARGS + } } diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatStrictDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatStrictDescriptor.java index b51f66a..7c1a88d 100644 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatStrictDescriptor.java +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordConcatStrictDescriptor.java @@ -45,18 +45,20 @@ } }; - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 2L; private ARecordType[] argTypes; + private ARecordType listItemRecordType; @Override public void setImmutableStates(Object... states) { - argTypes = (ARecordType[]) states; + argTypes = (ARecordType[]) states[0]; + listItemRecordType = (ARecordType) states[1]; } @Override public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) { - return new RecordConcatEvalFactory(args, argTypes, true, sourceLoc); + return new RecordConcatEvalFactory(args, argTypes, listItemRecordType, true, sourceLoc); } @Override diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java index f5deda0..bc763bd 100644 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java @@ -36,6 +36,7 @@ import org.apache.asterix.om.types.ARecordType; import org.apache.asterix.om.types.ATypeTag; import org.apache.asterix.om.types.AUnionType; +import org.apache.asterix.om.types.AbstractCollectionType; import org.apache.asterix.om.types.IAType; import org.apache.asterix.om.utils.ConstantExpressionUtil; import org.apache.asterix.om.utils.RecordUtil; @@ -315,14 +316,34 @@ List<Mutable<ILogicalExpression>> args = f.getArguments(); int n = args.size(); ARecordType[] argRecordTypes = new ARecordType[n]; - for (int i = 0; i < n; i++) { - IAType argType = (IAType) context.getType(args.get(i).getValue()); - IAType t = TypeComputeUtils.getActualType(argType); - if (t.getTypeTag() == ATypeTag.OBJECT) { - argRecordTypes[i] = (ARecordType) t; + ARecordType listItemRecordType = null; + if (n == 1) { + // check and handle if it's the single argument list case + IAType t = getExprActualType(args.get(0).getValue(), context); + if (t.getTypeTag().isListType()) { + listItemRecordType = getListItemRecordType(t); + } else if (t.getTypeTag() == ATypeTag.OBJECT) { + argRecordTypes[0] = (ARecordType) t; + } + } else { + for (int i = 0; i < n; i++) { + IAType t = getExprActualType(args.get(i).getValue(), context); + if (t.getTypeTag() == ATypeTag.OBJECT) { + argRecordTypes[i] = (ARecordType) t; + } } } - fd.setImmutableStates((Object[]) argRecordTypes); + fd.setImmutableStates(argRecordTypes, listItemRecordType); + } + + private static IAType getExprActualType(ILogicalExpression expr, IVariableTypeEnvironment ctx) + throws AlgebricksException { + return TypeComputeUtils.getActualType((IAType) ctx.getType(expr)); + } + + private static ARecordType getListItemRecordType(IAType listType) { + IAType itemType = ((AbstractCollectionType) listType).getItemType(); + return itemType.getTypeTag() == ATypeTag.OBJECT ? (ARecordType) itemType : null; } } -- To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/14404 To unsubscribe, or for help writing mail filters, visit https://asterix-gerrit.ics.uci.edu/settings Gerrit-Project: asterixdb Gerrit-Branch: master Gerrit-Change-Id: I2bf24229b5390106d06049c43af972734c6f9fd2 Gerrit-Change-Number: 14404 Gerrit-PatchSet: 4 Gerrit-Owner: Ali Alsuliman <[email protected]> Gerrit-Reviewer: Ali Alsuliman <[email protected]> Gerrit-Reviewer: Anon. E. Moose #1000171 Gerrit-Reviewer: Dmitry Lychagin <[email protected]> Gerrit-Reviewer: Jenkins <[email protected]> Gerrit-Reviewer: Till Westmann <[email protected]> Gerrit-MessageType: merged
