[ASTERIXDB-3287][SQL++] Allow PATH to have multiple expressions
- user model changes: yes
- storage format changes: no
- interface changes: no
Details:
- Allow users to sepcify multiple expressions in the
PATH clause in COPY TO
- The result of the multiple expressions will be
concatenated by a sperator char
Change-Id: I62a4616a4fc12bdb57fe5a673efff0aa87dbdc46
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17892
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Wail Alkowaileet <wael.y.k@gmail.com>
Reviewed-by: Murtadha Hubail <mhubail@apache.org>
Tested-by: Wail Alkowaileet <wael.y.k@gmail.com>
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyToStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyToStatement.java
index 52e3570..5f13960 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyToStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CopyToStatement.java
@@ -30,7 +30,9 @@
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.IReturningStatement;
import org.apache.asterix.lang.common.clause.OrderbyClause;
+import org.apache.asterix.lang.common.expression.LiteralExpr;
import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.literal.StringLiteral;
import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
public class CopyToStatement extends AbstractStatement implements IReturningStatement {
@@ -43,29 +45,34 @@
private final List<OrderbyClause.NullOrderModifier> orderbyNullModifierList;
private Query query;
- private Expression pathExpression;
+ private List<Expression> pathExpressions;
private List<Expression> partitionExpressions;
private List<Expression> orderbyList;
private int varCounter;
public CopyToStatement(Namespace namespace, String datasetName, Query query, VariableExpr sourceVariable,
- ExternalDetailsDecl externalDetailsDecl, Expression pathExpression, List<Expression> partitionExpressions,
- Map<Integer, VariableExpr> partitionsVariables, List<Expression> orderbyList,
- List<OrderbyClause.OrderModifier> orderbyModifiers,
+ ExternalDetailsDecl externalDetailsDecl, List<Expression> pathExpressions,
+ List<Expression> partitionExpressions, Map<Integer, VariableExpr> partitionsVariables,
+ List<Expression> orderbyList, List<OrderbyClause.OrderModifier> orderbyModifiers,
List<OrderbyClause.NullOrderModifier> orderbyNullModifierList, int varCounter) {
this.namespace = namespace;
this.datasetName = datasetName;
this.query = query;
this.sourceVariable = sourceVariable;
this.externalDetailsDecl = externalDetailsDecl;
- this.pathExpression = pathExpression;
+ this.pathExpressions = pathExpressions;
this.partitionExpressions = partitionExpressions;
this.partitionsVariables = partitionsVariables;
this.orderbyList = orderbyList;
this.orderbyModifiers = orderbyModifiers;
this.orderbyNullModifierList = orderbyNullModifierList;
this.varCounter = varCounter;
+
+ if (pathExpressions.isEmpty()) {
+ // Ensure path expressions to have at least an empty string
+ pathExpressions.add(new LiteralExpr(new StringLiteral("")));
+ }
}
@Override
@@ -107,12 +114,15 @@
return externalDetailsDecl;
}
- public Expression getPathExpression() {
- return pathExpression;
+ public List<Expression> getPathExpressions() {
+ return pathExpressions;
}
- public void setPathExpression(Expression pathExpression) {
- this.pathExpression = pathExpression;
+ public void setPathExpressions(List<Expression> pathExpressions) {
+ if (pathExpressions.isEmpty()) {
+ pathExpressions.add(new LiteralExpr(new StringLiteral("")));
+ }
+ this.pathExpressions = pathExpressions;
}
public List<Expression> getPartitionExpressions() {
@@ -170,7 +180,7 @@
public List<Expression> getDirectlyEnclosedExpressions() {
List<Expression> topLevelExpressions = new ArrayList<>();
topLevelExpressions.add(query.getBody());
- topLevelExpressions.add(pathExpression);
+ topLevelExpressions.addAll(pathExpressions);
topLevelExpressions.addAll(partitionExpressions);
topLevelExpressions.addAll(orderbyList);
return topLevelExpressions;
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
index d91873c..22c011a 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
@@ -290,9 +290,9 @@
changed |= queryBody.first;
stmtCopy.setBody(queryBody.second);
- Pair<Boolean, Expression> path = inlineUdfsAndViewsInExpr(stmtCopy.getPathExpression());
+ Pair<Boolean, List<Expression>> path = inlineUdfsInExprList(stmtCopy.getPathExpressions());
changed |= path.first;
- stmtCopy.setPathExpression(path.second);
+ stmtCopy.setPathExpressions(path.second);
Pair<Boolean, List<Expression>> part = inlineUdfsInExprList(stmtCopy.getPartitionExpressions());
changed |= part.first;
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
index 7ac9967..9c904da 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
@@ -574,7 +574,7 @@
out.println();
out.print("path (");
- cto.getPathExpression().accept(this, step + 1);
+ printDelimitedExpressions(cto.getPathExpressions(), COMMA, step + 1);
out.print(")");
out.println();
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
index 4ea7789..3373495 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
@@ -252,7 +252,7 @@
@Override
public Void visit(CopyToStatement stmtCopy, Void arg) throws CompilationException {
stmtCopy.getQuery().accept(this, arg);
- stmtCopy.getPathExpression().accept(this, arg);
+ acceptList(stmtCopy.getPathExpressions(), arg);
acceptList(stmtCopy.getPartitionExpressions(), arg);
acceptList(stmtCopy.getOrderbyList(), arg);
return null;
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
index 387b7f7..abae3ee 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
@@ -315,7 +315,7 @@
@Override
public Boolean visit(CopyToStatement stmtCopy, ILangExpression arg) throws CompilationException {
- return stmtCopy.getQuery().accept(this, arg) || stmtCopy.getPathExpression().accept(this, arg)
+ return stmtCopy.getQuery().accept(this, arg) || visitExprList(stmtCopy.getPathExpressions(), arg)
|| visitExprList(stmtCopy.getPartitionExpressions(), arg)
|| visitExprList(stmtCopy.getOrderbyList(), arg);
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
index c1c124a..45fd4bf 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
@@ -516,7 +516,7 @@
@Override
public Void visit(CopyToStatement stmtCopy, Collection<VariableExpr> freeVars) throws CompilationException {
stmtCopy.getBody().accept(this, freeVars);
- stmtCopy.getPathExpression().accept(this, freeVars);
+ visit(stmtCopy.getPathExpressions(), freeVars);
visit(stmtCopy.getPartitionExpressions(), freeVars);
visit(stmtCopy.getOrderbyList(), freeVars);
return null;
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java
index 368cf1d..39fe905a 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java
@@ -310,7 +310,7 @@
@Override
public Boolean visit(CopyToStatement stmtCopy, T arg) throws CompilationException {
- return stmtCopy.getQuery().accept(this, arg) || stmtCopy.getPathExpression().accept(this, arg)
+ return stmtCopy.accept(this, arg) || visitExprList(stmtCopy.getPathExpressions(), arg)
|| visitExprList(stmtCopy.getPartitionExpressions(), arg)
|| visitExprList(stmtCopy.getOrderbyList(), arg);
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
index f2519f1..1ecc3a2 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
@@ -434,8 +434,8 @@
// Visit order by
stmtCopy.setOrderbyList(visit(stmtCopy.getOrderbyList(), stmtCopy));
- // Visit path expr
- stmtCopy.setPathExpression(stmtCopy.getPathExpression().accept(this, stmtCopy));
+ // Visit path exprs
+ stmtCopy.setPathExpressions(visit(stmtCopy.getPathExpressions(), stmtCopy));
return null;
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
index 16fe67a..9b2501d 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
@@ -361,7 +361,7 @@
@Override
public Expression visit(CopyToStatement stmtCopy, ILangExpression arg) throws CompilationException {
stmtCopy.setBody(stmtCopy.getBody().accept(this, arg));
- stmtCopy.setPathExpression(stmtCopy.getPathExpression().accept(this, arg));
+ stmtCopy.setPathExpressions(visit(stmtCopy.getPathExpressions(), arg));
stmtCopy.setPartitionExpressions(visit(stmtCopy.getPartitionExpressions(), arg));
stmtCopy.setOrderbyList(visit(stmtCopy.getOrderbyList(), arg));
return null;
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index f2dc18e..a665015 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -2860,24 +2860,24 @@
Statement CopyStatement() throws ParseException:
{
- Token startToken = null;
- Pair<Namespace,Identifier> nameComponents = null;
- Query query = null;
- Statement stmt = null;
- TypeExpression typeExpr = null;
- VariableExpr alias = null;
+ Token startToken = null;
+ Pair<Namespace,Identifier> nameComponents = null;
+ Query query = null;
+ Statement stmt = null;
+ TypeExpression typeExpr = null;
+ VariableExpr alias = null;
}
{
- <COPY>
- ( LOOKAHEAD(1) <INTO> { startToken = token; } nameComponents = QualifiedName() stmt = CopyFromStatement(startToken, nameComponents, typeExpr)
- | LOOKAHEAD(1) <LEFTPAREN> { startToken = token; } query = Query() <RIGHTPAREN> (<AS>)? alias = Variable() stmt = CopyToStatement(startToken, nameComponents, query, alias)
- | { startToken = token; } nameComponents = QualifiedName()
- (<AS>)? (typeExpr = DatasetTypeSpecification(RecordTypeDefinition.RecordKind.OPEN) | alias = Variable())?
- (stmt = CopyFromStatement(startToken, nameComponents, typeExpr) | stmt = CopyToStatement(startToken, nameComponents, query, alias))
- )
- {
- return stmt;
- }
+ <COPY>
+ ( LOOKAHEAD(1) <INTO> { startToken = token; } nameComponents = QualifiedName() stmt = CopyFromStatement(startToken, nameComponents, typeExpr)
+ | LOOKAHEAD(1) <LEFTPAREN> { startToken = token; } query = Query() <RIGHTPAREN> (<AS>)? alias = Variable() stmt = CopyToStatement(startToken, nameComponents, query, alias)
+ | { startToken = token; } nameComponents = QualifiedName()
+ (<AS>)? (typeExpr = DatasetTypeSpecification(RecordTypeDefinition.RecordKind.OPEN) | alias = Variable())?
+ (stmt = CopyFromStatement(startToken, nameComponents, typeExpr) | stmt = CopyToStatement(startToken, nameComponents, query, alias))
+ )
+ {
+ return stmt;
+ }
}
CopyFromStatement CopyFromStatement(Token startToken, Pair<Namespace, Identifier> nameComponents, TypeExpression typeExpr) throws ParseException:
@@ -2913,7 +2913,7 @@
RecordConstructor withRecord;
Namespace namespace = nameComponents == null ? null : nameComponents.first;
String datasetName = nameComponents == null ? null : nameComponents.second.getValue();
- Expression pathExpr = null;
+ List<Expression> pathExprs;
List<Expression> partitionExprs = new ArrayList<Expression>();
Map<Integer, VariableExpr> partitionVarExprs = new HashMap<Integer, VariableExpr>();
@@ -2923,7 +2923,7 @@
}
{
<TO> adapterName = AdapterName()
- <PATH> <LEFTPAREN> pathExpr = Expression() <RIGHTPAREN>
+ <PATH> <LEFTPAREN> pathExprs = ExpressionList() <RIGHTPAREN>
(CopyToOverClause(partitionExprs, partitionVarExprs, orderbyList, orderbyModifierList, orderbyNullModifierList))?
<WITH> withRecord = RecordConstructor()
{
@@ -2939,7 +2939,7 @@
usedAlias = new VariableExpr(SqlppVariableUtil.toInternalVariableIdentifier(datasetName));
}
- CopyToStatement stmt = new CopyToStatement(namespace, datasetName, query, usedAlias, edd, pathExpr,
+ CopyToStatement stmt = new CopyToStatement(namespace, datasetName, query, usedAlias, edd, pathExprs,
partitionExprs, partitionVarExprs, orderbyList, orderbyModifierList, orderbyNullModifierList, getVarCounter());
return addSourceLocation(stmt, startToken);
}