>From Abhishek Jindal <[email protected]>:
Abhishek Jindal has uploaded this change for review. (
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19366 )
Change subject: [WIP] [ASTERIXDB-3526] : SQL++ Update support #5.1
......................................................................
[WIP] [ASTERIXDB-3526] : SQL++ Update support #5.1
Ensure the records generated by our data-transform functions
are of transform type, so as to prevent altering user passed object
types
Change-Id: I46d22b1eddc10795e99fef4983de0d705bdcb950
---
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveDuplicateFieldsRule.java
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/visitor/ConstantFoldingVisitor.java
M
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/RecordConstructor.java
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
M
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/OpenRecordConstructorResultType.java
M
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ClosedRecordConstructorResultType.java
M
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SetExpressionTree.java
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetClosedRecordConstructorsRule.java
8 files changed, 134 insertions(+), 35 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/66/19366/1
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveDuplicateFieldsRule.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveDuplicateFieldsRule.java
index e924a4c..03ded65 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveDuplicateFieldsRule.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveDuplicateFieldsRule.java
@@ -103,10 +103,15 @@
boolean changed = false;
if
(function.getFunctionIdentifier().equals(BuiltinFunctions.OPEN_RECORD_CONSTRUCTOR)
||
function.getFunctionIdentifier().equals(BuiltinFunctions.CLOSED_RECORD_CONSTRUCTOR))
{
+ Mutable<ILogicalExpression> finalArgRef = null;
if (function.getArguments().size() % 2 != 0) {
- String functionName =
function.getFunctionIdentifier().getName();
- throw
CompilationException.create(ErrorCode.COMPILATION_INVALID_NUM_OF_ARGS,
expr.getSourceLocation(),
- functionName);
+ finalArgRef =
function.getArguments().get(function.getArguments().size() - 1);
+ if (finalArgRef.getValue().getExpressionTag() !=
LogicalExpressionTag.CONSTANT) {
+ String functionName =
function.getFunctionIdentifier().getName();
+ throw
CompilationException.create(ErrorCode.COMPILATION_INVALID_NUM_OF_ARGS,
+ expr.getSourceLocation(), functionName);
+ }
+ function.getArguments().remove(function.getArguments().size()
- 1);
}
fieldNames.clear();
Iterator<Mutable<ILogicalExpression>> iterator =
function.getArguments().iterator();
@@ -127,6 +132,8 @@
iterator.next();
}
}
+ if (finalArgRef != null)
+ function.getArguments().add(finalArgRef);
}
List<Mutable<ILogicalExpression>> arguments = function.getArguments();
for (int i = 0, size = arguments.size(); i < size; i++) {
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetClosedRecordConstructorsRule.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetClosedRecordConstructorsRule.java
index 50da592..c3b390a 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetClosedRecordConstructorsRule.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetClosedRecordConstructorsRule.java
@@ -110,35 +110,47 @@
boolean changed = false;
if
(expr.getFunctionIdentifier().equals(BuiltinFunctions.OPEN_RECORD_CONSTRUCTOR))
{
ARecordType reqType = (ARecordType)
TypeCastUtils.getRequiredType(expr);
+ boolean isTransform = false;
if (reqType == null || !reqType.isOpen()) {
+ Mutable<ILogicalExpression> finalArgRef = null;
int n = expr.getArguments().size();
- if (n % 2 > 0) {
- throw new
CompilationException(ErrorCode.COMPILATION_ERROR, expr.getSourceLocation(),
- "Record constructor expected to have an even
number of arguments: "
- +
LogRedactionUtil.userData(expr.toString()));
+ if (expr.getArguments().size() % 2 != 0) {
+ finalArgRef =
expr.getArguments().get(expr.getArguments().size() - 1);
+ if (finalArgRef.getValue().getExpressionTag() !=
LogicalExpressionTag.CONSTANT) {
+ throw new
CompilationException(ErrorCode.COMPILATION_ERROR, expr.getSourceLocation(),
+ "Record constructor expected to have an
even number of arguments: "
+ +
LogRedactionUtil.userData(expr.toString()));
+ }
+ ConstantExpression cExpr = (ConstantExpression)
finalArgRef.getValue();
+ isTransform = cExpr.getValue().isTrue();
}
- for (int i = 0; i < n / 2; i++) {
- ILogicalExpression a0 = expr.getArguments().get(2 *
i).getValue();
- if (a0.getExpressionTag() !=
LogicalExpressionTag.CONSTANT) {
- allClosed = false;
+ /** Only attempt to convert this record into a closed form
if this is
+ * not a transform_object type */
+ if (!isTransform) {
+ for (int i = 0; i < n / 2; i++) {
+ ILogicalExpression a0 = expr.getArguments().get(2
* i).getValue();
+ if (a0.getExpressionTag() !=
LogicalExpressionTag.CONSTANT) {
+ allClosed = false;
+ }
+ Mutable<ILogicalExpression> aRef1 =
expr.getArguments().get(2 * i + 1);
+ ILogicalExpression a1 = aRef1.getValue();
+ ClosedDataInfo cdi = a1.accept(this, arg);
+ if (!cdi.dataIsClosed) {
+ allClosed = false;
+ }
+ if (cdi.expressionChanged) {
+ aRef1.setValue(cdi.expression);
+ changed = true;
+ }
}
- Mutable<ILogicalExpression> aRef1 =
expr.getArguments().get(2 * i + 1);
- ILogicalExpression a1 = aRef1.getValue();
- ClosedDataInfo cdi = a1.accept(this, arg);
- if (!cdi.dataIsClosed) {
- allClosed = false;
- }
- if (cdi.expressionChanged) {
- aRef1.setValue(cdi.expression);
+ if (allClosed) {
+ expr.setFunctionInfo(
+
FunctionUtil.getFunctionInfo(BuiltinFunctions.CLOSED_RECORD_CONSTRUCTOR));
+ AlgebricksConfig.ALGEBRICKS_LOGGER.trace(() ->
"Switching to CLOSED record constructor in "
+ +
LogRedactionUtil.userData(expr.toString()) + ".\n");
changed = true;
}
}
- if (allClosed) {
-
expr.setFunctionInfo(FunctionUtil.getFunctionInfo(BuiltinFunctions.CLOSED_RECORD_CONSTRUCTOR));
- AlgebricksConfig.ALGEBRICKS_LOGGER.trace(() ->
"Switching to CLOSED record constructor in "
- + LogRedactionUtil.userData(expr.toString()) +
".\n");
- changed = true;
- }
}
} else {
boolean rewrite = true;
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/visitor/ConstantFoldingVisitor.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/visitor/ConstantFoldingVisitor.java
index 0feb6c5..e72fc47 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/visitor/ConstantFoldingVisitor.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/visitor/ConstantFoldingVisitor.java
@@ -294,10 +294,15 @@
}
private boolean foldRecordArgs(AbstractFunctionCallExpression expr, Void
arg) throws AlgebricksException {
+ Mutable<ILogicalExpression> finalArgRef = null;
if (expr.getArguments().size() % 2 != 0) {
- String functionName = expr.getFunctionIdentifier().getName();
- throw
CompilationException.create(ErrorCode.COMPILATION_INVALID_NUM_OF_ARGS,
expr.getSourceLocation(),
- functionName);
+ finalArgRef = expr.getArguments().get(expr.getArguments().size() -
1);
+ if (finalArgRef.getValue().getExpressionTag() !=
LogicalExpressionTag.CONSTANT) {
+ String functionName = expr.getFunctionIdentifier().getName();
+ throw
CompilationException.create(ErrorCode.COMPILATION_INVALID_NUM_OF_ARGS,
expr.getSourceLocation(),
+ functionName);
+ }
+ expr.getArguments().remove(expr.getArguments().size() - 1);
}
boolean changed = false;
Iterator<Mutable<ILogicalExpression>> iterator =
expr.getArguments().iterator();
@@ -331,6 +336,8 @@
fieldNameIdx += 2;
}
}
+ if (finalArgRef != null)
+ expr.getArguments().add(finalArgRef);
return changed;
}
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index 978997c..b337d9d 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -1676,6 +1676,9 @@
f.getArguments().add(new MutableObject<>(eo2.first));
topOp = eo2.second;
}
+ if (rc.isTransformRecord()) {
+ f.getArguments().add(new
MutableObject<>(createConstantExpression(ABoolean.TRUE,
rc.getSourceLocation())));
+ }
a.getInputs().add(topOp);
return new Pair<>(a, v1);
}
diff --git
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/RecordConstructor.java
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/RecordConstructor.java
index cce92e6..3fb4a63 100644
---
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/RecordConstructor.java
+++
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/RecordConstructor.java
@@ -27,16 +27,22 @@
public class RecordConstructor extends AbstractExpression {
private List<FieldBinding> fbList;
+ private boolean isTransformRecord;
public RecordConstructor() {
super();
}
public RecordConstructor(List<FieldBinding> fbList) {
- super();
+ this();
this.fbList = fbList;
}
+ public RecordConstructor(List<FieldBinding> fbList, boolean
isTransformRecord) {
+ this(fbList);
+ this.isTransformRecord = isTransformRecord;
+ }
+
public List<FieldBinding> getFbList() {
return fbList;
}
@@ -45,6 +51,10 @@
this.fbList = fbList;
}
+ public boolean isTransformRecord() {
+ return isTransformRecord;
+ }
+
@Override
public Kind getKind() {
return Kind.RECORD_CONSTRUCTOR_EXPRESSION;
@@ -71,4 +81,4 @@
RecordConstructor target = (RecordConstructor) object;
return Objects.equals(fbList, target.fbList);
}
-}
+}
\ No newline at end of file
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 9262a1e..b1ca0628 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
@@ -142,9 +142,9 @@
Expression deletionRecord = null;
Expression setRecord = null;
if (setRecordArgs.size() > 0)
- setRecord = new RecordConstructor(setRecordArgs);
+ setRecord = new RecordConstructor(setRecordArgs, true);
if (deletionRecordArgs.size() > 0)
- deletionRecord = new RecordConstructor(deletionRecordArgs);
+ deletionRecord = new RecordConstructor(deletionRecordArgs, false);
return new Pair<>(setRecord, deletionRecord);
}
diff --git
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ClosedRecordConstructorResultType.java
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ClosedRecordConstructorResultType.java
index d3cb2d7..14a19dc 100644
---
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ClosedRecordConstructorResultType.java
+++
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ClosedRecordConstructorResultType.java
@@ -24,6 +24,7 @@
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.om.exceptions.InvalidExpressionException;
+import org.apache.asterix.om.exceptions.TypeMismatchException;
import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
import org.apache.asterix.om.typecomputer.base.TypeCastUtils;
import org.apache.asterix.om.types.ARecordType;
@@ -36,6 +37,7 @@
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
import
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
import
org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
import org.apache.hyracks.util.LogRedactionUtil;
@@ -57,6 +59,21 @@
return type;
}
+ Mutable<ILogicalExpression> finalArgRef = null;
+ boolean isTransform = false;
+ if (f.getArguments().size() % 2 != 0) {
+ finalArgRef = f.getArguments().get(f.getArguments().size() - 1);
+ if (finalArgRef.getValue().getExpressionTag() !=
LogicalExpressionTag.CONSTANT) {
+ IAType finalArgType = (IAType)
env.getType(finalArgRef.getValue());
+ throw new TypeMismatchException(f.getSourceLocation(),
f.getFunctionIdentifier(),
+ f.getArguments().size() - 1,
finalArgType.getTypeTag(), ATypeTag.BOOLEAN);
+ }
+ ConstantExpression cExpr = (ConstantExpression)
finalArgRef.getValue();
+ if (cExpr.getValue().isTrue())
+ isTransform = true;
+ f.getArguments().remove(f.getArguments().size() - 1);
+ }
+
int n = f.getArguments().size() / 2;
String[] fieldNames = new String[n];
IAType[] fieldTypes = new IAType[n];
@@ -85,6 +102,11 @@
fieldNames[i] = fieldName;
i++;
}
- return new ARecordType(null, fieldNames, fieldTypes, false);
+
+ if (finalArgRef != null)
+ f.getArguments().add(finalArgRef);
+ ARecordType resultType = new ARecordType(null, fieldNames, fieldTypes,
false);
+ resultType.setIsTransform(isTransform);
+ return resultType;
}
-}
+}
\ No newline at end of file
diff --git
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/OpenRecordConstructorResultType.java
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/OpenRecordConstructorResultType.java
index 8358627..02ac4b6 100644
---
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/OpenRecordConstructorResultType.java
+++
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/OpenRecordConstructorResultType.java
@@ -31,6 +31,7 @@
import org.apache.asterix.common.config.CompilerProperties;
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.om.exceptions.TypeMismatchException;
import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
import org.apache.asterix.om.typecomputer.base.TypeCastUtils;
import org.apache.asterix.om.types.ARecordType;
@@ -42,7 +43,9 @@
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
import
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
import
org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
import org.apache.hyracks.algebricks.core.config.AlgebricksConfig;
@@ -72,6 +75,21 @@
.getOrDefault(CompilerProperties.COMPILER_ORDERED_FIELDS_KEY,
String.valueOf(orderFields)));
}
+ Mutable<ILogicalExpression> finalArgRef = null;
+ boolean isTransform = false;
+ if (f.getArguments().size() % 2 != 0) {
+ finalArgRef = f.getArguments().get(f.getArguments().size() - 1);
+ if (finalArgRef.getValue().getExpressionTag() !=
LogicalExpressionTag.CONSTANT) {
+ IAType finalArgType = (IAType)
env.getType(finalArgRef.getValue());
+ throw new TypeMismatchException(f.getSourceLocation(),
f.getFunctionIdentifier(),
+ f.getArguments().size() - 1,
finalArgType.getTypeTag(), ATypeTag.BOOLEAN);
+ }
+ ConstantExpression cExpr = (ConstantExpression)
finalArgRef.getValue();
+ if (cExpr.getValue().isTrue())
+ isTransform = true;
+ f.getArguments().remove(f.getArguments().size() - 1);
+ }
+
Iterator<Mutable<ILogicalExpression>> argIter =
f.getArguments().iterator();
List<String> namesList = new ArrayList<>();
List<IAType> typesList = new ArrayList<>();
@@ -108,6 +126,12 @@
}
allPossibleFieldNamesOrdered.add(fieldName);
}
+ if (finalArgRef != null)
+ f.getArguments().add(finalArgRef);
+ // We always want the transform record to be welcoming of other fields
+ // from the data transformation apart from itself. This is why such is
record is always open.
+ if (isTransform)
+ isOpen = true;
String[] fieldNames = namesList.toArray(new String[0]);
IAType[] fieldTypes = typesList.toArray(new IAType[0]);
ARecordType resultType;
@@ -122,6 +146,7 @@
} else {
resultType = new ARecordType(null, fieldNames, fieldTypes, isOpen);
}
+ resultType.setIsTransform(isTransform);
return resultType;
}
-}
+}
\ No newline at end of file
--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19366
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: I46d22b1eddc10795e99fef4983de0d705bdcb950
Gerrit-Change-Number: 19366
Gerrit-PatchSet: 1
Gerrit-Owner: Abhishek Jindal <[email protected]>
Gerrit-MessageType: newchange