[NO ISSUE][SQLPP] Optional field name in object constructor
- user model changes: yes
- storage format changes: no
- interface changes: no
Details:
- Allow field name to be optional in object constructors.
If missing then it will be inferred from a field value
expression in a manner similar to unnamed projections.
- Add documentation and testcases
Change-Id: I0dfba8f8137f88d934a5be8ffb5fbc1c1db0bb58
Reviewed-on: https://asterix-gerrit.ics.uci.edu/3424
Sonar-Qube: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
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 b91a5ef..e0114fc 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
@@ -103,6 +103,17 @@
</compilation-unit>
</test-case>
<test-case FilePath="objects">
+ <compilation-unit name="no_fieldname_constr">
+ <output-dir compare="Text">no_fieldname_constr</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="objects">
+ <compilation-unit name="no_fieldname_constr_negative">
+ <output-dir compare="Text">no_fieldname_constr</output-dir>
+ <expected-error>ASX1001: Syntax error: Cannot infer field name</expected-error>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="objects">
<compilation-unit name="object_concat">
<output-dir compare="Text">object_concat</output-dir>
</compilation-unit>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/no_fieldname_constr/no_fieldname_constr.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/no_fieldname_constr/no_fieldname_constr.1.query.sqlpp
new file mode 100644
index 0000000..13d9fff
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/no_fieldname_constr/no_fieldname_constr.1.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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 constructor without field names
+ * Expected Res : Success
+ */
+
+ from range(1, 2) x, range(3, 4) y
+ select value { x, y }
+ order by x, y
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/no_fieldname_constr/no_fieldname_constr.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/no_fieldname_constr/no_fieldname_constr.2.query.sqlpp
new file mode 100644
index 0000000..7ffab82
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/no_fieldname_constr/no_fieldname_constr.2.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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 constructor without field names
+ * Expected Res : Success
+ */
+
+ from (from range(1, 2) x select x) y
+ select value { y.x }
+ order by y.x
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/no_fieldname_constr_negative/no_fieldname_constr_negative.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/no_fieldname_constr_negative/no_fieldname_constr_negative.1.query.sqlpp
new file mode 100644
index 0000000..edcefcf
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/objects/no_fieldname_constr_negative/no_fieldname_constr_negative.1.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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 constructor without field names
+ * Expected Res : Failure: Cannot infer field name
+ */
+
+ from range(1, 2) x
+ select value { x + 1 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/no_fieldname_constr/no_fieldname_constr.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/no_fieldname_constr/no_fieldname_constr.1.adm
new file mode 100644
index 0000000..ffd1e6c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/no_fieldname_constr/no_fieldname_constr.1.adm
@@ -0,0 +1,4 @@
+{ "x": 1, "y": 3 }
+{ "x": 1, "y": 4 }
+{ "x": 2, "y": 3 }
+{ "x": 2, "y": 4 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/no_fieldname_constr/no_fieldname_constr.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/no_fieldname_constr/no_fieldname_constr.2.adm
new file mode 100644
index 0000000..1379125
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/objects/no_fieldname_constr/no_fieldname_constr.2.adm
@@ -0,0 +1,2 @@
+{ "x": 1 }
+{ "x": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-doc/src/main/markdown/sqlpp/2_expr.md b/asterixdb/asterix-doc/src/main/markdown/sqlpp/2_expr.md
index ef19dca..efc2a86 100644
--- a/asterixdb/asterix-doc/src/main/markdown/sqlpp/2_expr.md
+++ b/asterixdb/asterix-doc/src/main/markdown/sqlpp/2_expr.md
@@ -423,7 +423,7 @@
ArrayConstructor ::= "[" ( Expression ( "," Expression )* )? "]"
MultisetConstructor ::= "{{" ( Expression ( "," Expression )* )? "}}"
ObjectConstructor ::= "{" ( FieldBinding ( "," FieldBinding )* )? "}"
- FieldBinding ::= Expression ":" Expression
+ FieldBinding ::= Expression ( ":" Expression )?
A major feature of the query language is its ability to construct new data model instances. This is accomplished using
its constructors for each of the model's complex object structures, namely arrays, multisets, and objects.
@@ -450,3 +450,25 @@
'project members': [ 'vinayakb', 'dtabass', 'chenli', 'tsotras', 'tillw' ]
}
+
+If only one expression is specified instead of the field-name/field-value pair in an object constructor then this
+expression is supposed to provide the field value. The field name is then automatically generated based on the
+kind of the value expression:
+
+ * If it is a variable reference expression then generated field name is the name of that variable.
+ * If it is a field access expression then generated field name is the last identifier in that expression.
+ * For all other cases, a compilation error will be raised.
+
+##### Example
+
+ SELECT VALUE { user.alias, user.userSince }
+ FROM GleambookUsers user
+ WHERE user.id = 1;
+
+This query outputs:
+
+ [ {
+ "alias": "Margarita",
+ "userSince": "2012-08-20T10:10:00"
+ } ]
+
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index 6f63441..73612ab 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -2690,12 +2690,21 @@
FieldBinding FieldBinding() throws ParseException:
{
- Expression left, right;
+ Expression left, right = null;
}
{
- left = Expression() <COLON> right = Expression()
+ left = Expression() ( <COLON> right = Expression() )?
{
- return new FieldBinding(left, right);
+ if (right == null) {
+ String generatedIdentifier = ExpressionToVariableUtil.getGeneratedIdentifier(left, false);
+ if (generatedIdentifier == null) {
+ throw new SqlppParseException(getSourceLocation(token), "Cannot infer field name");
+ }
+ String generatedName = SqlppVariableUtil.toUserDefinedName(generatedIdentifier);
+ return new FieldBinding(new LiteralExpr(new StringLiteral(generatedName)), left);
+ } else {
+ return new FieldBinding(left, right);
+ }
}
}