This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch ty/TableModelGrammar
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/ty/TableModelGrammar by this
push:
new b1278912731 partial
b1278912731 is described below
commit b1278912731a0795985fc36d2618029fd8435ba4
Author: JackieTien97 <[email protected]>
AuthorDate: Sun Feb 18 12:35:51 2024 +0800
partial
---
.../db/relational/sql/parser/ParsingException.java | 68 +++++++
.../db/relational/sql/tree/AliasedRelation.java | 110 ++++++++++++
.../iotdb/db/relational/sql/tree/AstVisitor.java | 1 +
.../db/relational/sql/tree/BinaryLiteral.java | 108 +++++++++++
.../db/relational/sql/tree/BooleanLiteral.java | 85 +++++++++
.../db/relational/sql/tree/DecimalLiteral.java | 77 ++++++++
.../db/relational/sql/tree/DoubleLiteral.java | 80 +++++++++
.../iotdb/db/relational/sql/tree/Expression.java | 2 +
.../db/relational/sql/tree/GenericLiteral.java | 102 +++++++++++
.../tree/{Literal.java => IsNotNullPredicate.java} | 51 +++++-
.../tree/{Literal.java => IsNullPredicate.java} | 51 +++++-
.../apache/iotdb/db/relational/sql/tree/Join.java | 154 ++++++++++++++++
.../sql/tree/{Literal.java => JoinCriteria.java} | 23 +--
.../sql/tree/{Literal.java => JoinOn.java} | 46 ++++-
.../sql/tree/{Literal.java => JoinUsing.java} | 46 ++++-
.../db/relational/sql/tree/LikePredicate.java | 107 +++++++++++
.../apache/iotdb/db/relational/sql/tree/Limit.java | 98 ++++++++++
.../iotdb/db/relational/sql/tree/Literal.java | 3 +-
.../db/relational/sql/tree/LogicalExpression.java | 114 ++++++++++++
.../iotdb/db/relational/sql/tree/LongLiteral.java | 109 ++++++++++++
.../sql/tree/{Literal.java => NaturalJoin.java} | 25 ++-
.../apache/iotdb/db/relational/sql/tree/Node.java | 2 +-
.../sql/tree/{Literal.java => NotExpression.java} | 51 +++++-
.../sql/tree/{Literal.java => NullLiteral.java} | 36 +++-
.../iotdb/db/relational/sql/tree/Offset.java | 95 ++++++++++
.../iotdb/db/relational/sql/tree/OrderBy.java | 91 ++++++++++
.../sql/tree/{Literal.java => Parameter.java} | 52 +++++-
.../sql/tree/QuantifiedComparisonExpression.java | 116 ++++++++++++
.../apache/iotdb/db/relational/sql/tree/Query.java | 159 +++++++++++++++++
.../sql/tree/{Literal.java => QueryBody.java} | 13 +-
.../db/relational/sql/tree/QuerySpecification.java | 198 +++++++++++++++++++++
.../sql/tree/{Literal.java => Relation.java} | 16 +-
.../sql/tree/SearchedCaseExpression.java | 107 +++++++++++
.../relational/sql/tree/SimpleCaseExpression.java | 120 +++++++++++++
.../iotdb/db/relational/sql/tree/SortItem.java | 118 ++++++++++++
.../db/relational/sql/tree/StringLiteral.java | 82 +++++++++
.../tree/{Literal.java => SubqueryExpression.java} | 51 +++++-
.../tree/{Literal.java => SymbolReference.java} | 36 +++-
.../apache/iotdb/db/relational/sql/tree/Trim.java | 138 ++++++++++++++
.../iotdb/db/relational/sql/tree/WhenClause.java | 87 +++++++++
.../apache/iotdb/db/relational/sql/tree/With.java | 105 +++++++++++
.../iotdb/db/relational/sql/tree/WithQuery.java | 129 ++++++++++++++
.../relational/sql/util/ExpressionFormatter.java | 2 +
43 files changed, 3150 insertions(+), 114 deletions(-)
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/ParsingException.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/ParsingException.java
new file mode 100644
index 00000000000..281490f4dd3
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/ParsingException.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.parser;
+
+import org.antlr.v4.runtime.RecognitionException;
+import org.apache.iotdb.db.relational.sql.tree.NodeLocation;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+public class ParsingException extends RuntimeException {
+ private final int line;
+ private final int column;
+
+ public ParsingException(String message, RecognitionException cause, int
line, int column) {
+ super(message, cause);
+ checkArgument(line > 0, "line must be > 0");
+ checkArgument(column > 0, "column must be > 0");
+
+ this.line = line;
+ this.column = column;
+ }
+
+ public ParsingException(String message) {
+ this(message, null, 1, 1);
+ }
+
+ public ParsingException(String message, RecognitionException cause) {
+ this(message, cause, 1, 1);
+ }
+
+ public ParsingException(String message, NodeLocation nodeLocation) {
+ this(message, null, nodeLocation.getLineNumber(),
nodeLocation.getColumnNumber());
+ }
+
+ public int getLineNumber() {
+ return line;
+ }
+
+ public int getColumnNumber() {
+ return column;
+ }
+
+ public String getErrorMessage() {
+ return super.getMessage();
+ }
+
+ @Override
+ public String getMessage() {
+ return String.format("line %s:%s: %s", getLineNumber(), getColumnNumber(),
getErrorMessage());
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AliasedRelation.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AliasedRelation.java
new file mode 100644
index 00000000000..231b9e229d9
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AliasedRelation.java
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static java.util.Objects.requireNonNull;
+
+public class AliasedRelation extends Relation {
+ private final Relation relation;
+ private final Identifier alias;
+ private final List<Identifier> columnNames;
+
+ public AliasedRelation(Relation relation, Identifier alias, List<Identifier>
columnNames) {
+ super(null);
+ this.relation = requireNonNull(relation, "relation is null");
+ this.alias = requireNonNull(alias, "alias is null");
+ this.columnNames = columnNames;
+ }
+
+ public AliasedRelation(NodeLocation location, Relation relation, Identifier
alias, List<Identifier> columnNames) {
+ super(requireNonNull(location, "location is null"));
+ this.relation = requireNonNull(relation, "relation is null");
+ this.alias = requireNonNull(alias, "alias is null");
+ this.columnNames = columnNames;
+ }
+
+ public Relation getRelation() {
+ return relation;
+ }
+
+ public Identifier getAlias() {
+ return alias;
+ }
+
+ public List<Identifier> getColumnNames() {
+ return columnNames;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitAliasedRelation(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ return ImmutableList.of(relation);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("relation", relation)
+ .add("alias", alias)
+ .add("columnNames", columnNames)
+ .omitNullValues()
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ AliasedRelation that = (AliasedRelation) o;
+ return Objects.equals(relation, that.relation) &&
+ Objects.equals(alias, that.alias) &&
+ Objects.equals(columnNames, that.columnNames);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(relation, alias, columnNames);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ AliasedRelation otherRelation = (AliasedRelation) other;
+ return alias.equals(otherRelation.alias) && Objects.equals(columnNames,
otherRelation.columnNames);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
index 607c3a1a93b..f6aca0f4d28 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/AstVisitor.java
@@ -19,6 +19,7 @@
package org.apache.iotdb.db.relational.sql.tree;
+
import javax.annotation.Nullable;
public abstract class AstVisitor<R, C> {
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/BinaryLiteral.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/BinaryLiteral.java
new file mode 100644
index 00000000000..26f79356d6c
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/BinaryLiteral.java
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.io.BaseEncoding;
+import org.apache.iotdb.db.relational.sql.parser.ParsingException;
+
+import java.util.Arrays;
+
+import static java.util.Locale.ENGLISH;
+import static java.util.Objects.requireNonNull;
+
+public class BinaryLiteral extends Literal {
+ // the grammar could possibly include whitespace in the value it passes to us
+ private static final CharMatcher WHITESPACE_MATCHER =
CharMatcher.whitespace();
+ private static final CharMatcher HEX_DIGIT_MATCHER =
CharMatcher.inRange('A', 'F')
+ .or(CharMatcher.inRange('0', '9'))
+ .precomputed();
+
+ private final byte[] value;
+
+ public BinaryLiteral(String value) {
+ super(null);
+ requireNonNull(value, "value is null");
+ String hexString =
WHITESPACE_MATCHER.removeFrom(value).toUpperCase(ENGLISH);
+ if (!HEX_DIGIT_MATCHER.matchesAllOf(hexString)) {
+ throw new ParsingException("Binary literal can only contain hexadecimal
digits");
+ }
+ if (hexString.length() % 2 != 0) {
+ throw new ParsingException("Binary literal must contain an even number
of digits");
+ }
+ this.value = BaseEncoding.base16().decode(hexString);
+ }
+
+ public BinaryLiteral(NodeLocation location, String value) {
+ super(requireNonNull(location, "location is null"));
+ requireNonNull(value, "value is null");
+ String hexString =
WHITESPACE_MATCHER.removeFrom(value).toUpperCase(ENGLISH);
+ if (!HEX_DIGIT_MATCHER.matchesAllOf(hexString)) {
+ throw new ParsingException("Binary literal can only contain hexadecimal
digits", location);
+ }
+ if (hexString.length() % 2 != 0) {
+ throw new ParsingException("Binary literal must contain an even number
of digits", location);
+ }
+ this.value = BaseEncoding.base16().decode(hexString);
+ }
+
+ /**
+ * Return the valued as a hex-formatted string with upper-case characters
+ */
+ public String toHexString() {
+ return BaseEncoding.base16().encode(value);
+ }
+
+ public byte[] getValue() {
+ return value.clone();
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitBinaryLiteral(this, context);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ BinaryLiteral that = (BinaryLiteral) o;
+ return Arrays.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(value);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ return Arrays.equals(value, ((BinaryLiteral) other).value);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/BooleanLiteral.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/BooleanLiteral.java
new file mode 100644
index 00000000000..51ce7afece6
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/BooleanLiteral.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Locale.ENGLISH;
+import static java.util.Objects.requireNonNull;
+
+public class BooleanLiteral extends Literal {
+
+ public static final BooleanLiteral TRUE_LITERAL = new BooleanLiteral("true");
+ public static final BooleanLiteral FALSE_LITERAL = new
BooleanLiteral("false");
+
+ private final boolean value;
+
+ public BooleanLiteral(String value) {
+ super(null);
+ requireNonNull(value, "value is null");
+ checkArgument(value.toLowerCase(ENGLISH).equals("true") ||
value.toLowerCase(ENGLISH).equals("false"));
+
+ this.value = value.toLowerCase(ENGLISH).equals("true");
+ }
+
+ public BooleanLiteral(NodeLocation location, String value) {
+ super(requireNonNull(location, "location is null"));
+ requireNonNull(value, "value is null");
+ checkArgument(value.toLowerCase(ENGLISH).equals("true") ||
value.toLowerCase(ENGLISH).equals("false"));
+
+ this.value = value.toLowerCase(ENGLISH).equals("true");
+ }
+
+ public boolean getValue() {
+ return value;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitBooleanLiteral(this, context);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(value);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ BooleanLiteral other = (BooleanLiteral) obj;
+ return Objects.equals(this.value, other.value);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ return value == ((BooleanLiteral) other).value;
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DecimalLiteral.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DecimalLiteral.java
new file mode 100644
index 00000000000..21b217c207a
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DecimalLiteral.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class DecimalLiteral extends Literal {
+
+ private final String value;
+
+ public DecimalLiteral(String value) {
+ super(null);
+ this.value = requireNonNull(value, "value is null");
+ }
+
+ public DecimalLiteral(NodeLocation location, String value) {
+ super(requireNonNull(location, "location is null"));
+
+ this.value = requireNonNull(value, "value is null");
+
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitDecimalLiteral(this, context);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DecimalLiteral that = (DecimalLiteral) o;
+ return Objects.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(value);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ DecimalLiteral otherLiteral = (DecimalLiteral) other;
+ return value.equals(otherLiteral.value);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DoubleLiteral.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DoubleLiteral.java
new file mode 100644
index 00000000000..7d911f32a32
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DoubleLiteral.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import static java.util.Objects.requireNonNull;
+
+public class DoubleLiteral extends Literal {
+
+ private final double value;
+
+ public DoubleLiteral(String value) {
+ super(null);
+ this.value = Double.parseDouble(requireNonNull(value, "value is null"));
+ }
+
+ public DoubleLiteral(NodeLocation location, String value) {
+ super(requireNonNull(location, "location is null"));
+ this.value = Double.parseDouble(requireNonNull(value, "value is null"));
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitDoubleLiteral(this, context);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ DoubleLiteral that = (DoubleLiteral) o;
+
+ if (Double.compare(that.value, value) != 0) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @SuppressWarnings("UnaryPlus")
+ @Override
+ public int hashCode() {
+ long temp = value != +0.0d ? Double.doubleToLongBits(value) : 0L;
+ return (int) (temp ^ (temp >>> 32));
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ return value == ((DoubleLiteral) other).value;
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Expression.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Expression.java
index 2e401eaf4cd..98aee549f2e 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Expression.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Expression.java
@@ -19,6 +19,8 @@
package org.apache.iotdb.db.relational.sql.tree;
+import org.apache.iotdb.db.relational.sql.util.ExpressionFormatter;
+
import javax.annotation.Nullable;
public abstract class Expression extends Node {
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/GenericLiteral.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/GenericLiteral.java
new file mode 100644
index 00000000000..017c0272956
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/GenericLiteral.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import org.apache.iotdb.db.relational.sql.parser.ParsingException;
+
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class GenericLiteral extends Literal {
+
+ private final String type;
+ private final String value;
+
+ public GenericLiteral(String type, String value) {
+ super(null);
+ this.type = requireNonNull(type, "type is null");
+
+ if (type.equalsIgnoreCase("X")) {
+ // we explicitly disallow "X" as type name, so if the user arrived here,
+ // it must be because that he intended to give a binaryLiteral instead,
but
+ // added whitespace between the X and quote
+ throw new ParsingException("Spaces are not allowed between 'X' and the
starting quote of a binary literal");
+ }
+ this.value = requireNonNull(value, "value is null");
+ }
+
+ public GenericLiteral(NodeLocation location, String type, String value) {
+ super(requireNonNull(location, "location is null"));
+ this.type = requireNonNull(type, "type is null");
+
+ if (type.equalsIgnoreCase("X")) {
+ // we explicitly disallow "X" as type name, so if the user arrived here,
+ // it must be because that he intended to give a binaryLiteral instead,
but
+ // added whitespace between the X and quote
+ throw new ParsingException("Spaces are not allowed between 'X' and the
starting quote of a binary literal",
+ location);
+ }
+ this.value = requireNonNull(value, "value is null");
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitGenericLiteral(this, context);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(value, type);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ GenericLiteral other = (GenericLiteral) obj;
+ return Objects.equals(this.value, other.value) &&
+ Objects.equals(this.type, other.type);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ GenericLiteral otherLiteral = (GenericLiteral) other;
+
+ return value.equals(otherLiteral.value) && type.equals(otherLiteral.type);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/IsNotNullPredicate.java
similarity index 50%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/IsNotNullPredicate.java
index b61b0bbb9cd..8b8389982e0 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/IsNotNullPredicate.java
@@ -21,22 +21,59 @@ package org.apache.iotdb.db.relational.sql.tree;
import com.google.common.collect.ImmutableList;
-import javax.annotation.Nullable;
-
import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class IsNotNullPredicate extends Expression {
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
- super(location);
+ private final Expression value;
+
+ public IsNotNullPredicate(Expression value) {
+ super(null);
+ this.value = requireNonNull(value, "value is null");
+ }
+
+ public IsNotNullPredicate(NodeLocation location, Expression value) {
+ super(requireNonNull(location, "location is null"));
+ this.value = requireNonNull(value, "value is null");
+ }
+
+ public Expression getValue() {
+ return value;
}
@Override
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
+ return visitor.visitIsNotNullPredicate(this, context);
}
@Override
public List<Node> getChildren() {
- return ImmutableList.of();
+ return ImmutableList.of(value);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ IsNotNullPredicate that = (IsNotNullPredicate) o;
+ return Objects.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
}
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/IsNullPredicate.java
similarity index 50%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/IsNullPredicate.java
index b61b0bbb9cd..81de5b31f01 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/IsNullPredicate.java
@@ -21,22 +21,59 @@ package org.apache.iotdb.db.relational.sql.tree;
import com.google.common.collect.ImmutableList;
-import javax.annotation.Nullable;
-
import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class IsNullPredicate extends Expression {
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
- super(location);
+ private final Expression value;
+
+ public IsNullPredicate(Expression value) {
+ super(null);
+ this.value = requireNonNull(value, "value is null");
+ }
+
+ public IsNullPredicate(NodeLocation location, Expression value) {
+ super(requireNonNull(location, "location is null"));
+ this.value = requireNonNull(value, "value is null");
+ }
+
+ public Expression getValue() {
+ return value;
}
@Override
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
+ return visitor.visitIsNullPredicate(this, context);
}
@Override
public List<Node> getChildren() {
- return ImmutableList.of();
+ return ImmutableList.of(value);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ IsNullPredicate that = (IsNullPredicate) o;
+ return Objects.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
}
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Join.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Join.java
new file mode 100644
index 00000000000..cb1efad1f78
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Join.java
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import javax.annotation.Nullable;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class Join extends Relation {
+
+ public enum Type {
+ CROSS, INNER, LEFT, RIGHT, FULL, IMPLICIT
+ }
+
+ private final Type type;
+ private final Relation left;
+ private final Relation right;
+
+ @Nullable
+ private final JoinCriteria criteria;
+
+ public Join(Type type, Relation left, Relation right) {
+ super(null);
+ this.criteria = null;
+ checkArgument((type == Type.CROSS) || (type == Type.IMPLICIT), "No join
criteria specified");
+ this.type = type;
+ this.left = requireNonNull(left, "left is null");
+ this.right = requireNonNull(right, "right is null");
+ }
+
+ public Join(NodeLocation location, Type type, Relation left, Relation right)
{
+ super(requireNonNull(location, "location is null"));
+ this.criteria = null;
+ checkArgument((type == Type.CROSS) || (type == Type.IMPLICIT), "No join
criteria specified");
+ this.type = type;
+ this.left = requireNonNull(left, "left is null");
+ this.right = requireNonNull(right, "right is null");
+ }
+
+ public Join(Type type, Relation left, Relation right, JoinCriteria criteria)
{
+ super(null);
+ this.criteria = requireNonNull(criteria, "criteria is null");
+ checkArgument(!((type == Type.CROSS) || (type == Type.IMPLICIT)), "%s join
cannot have join criteria", type);
+ this.type = type;
+ this.left = requireNonNull(left, "left is null");
+ this.right = requireNonNull(right, "right is null");
+ }
+
+ public Join(NodeLocation location, Type type, Relation left, Relation right,
JoinCriteria criteria) {
+ super(requireNonNull(location, "location is null"));
+ this.criteria = requireNonNull(criteria, "criteria is null");
+ checkArgument(!((type == Type.CROSS) || (type == Type.IMPLICIT)), "%s join
cannot have join criteria", type);
+ this.type = type;
+ this.left = requireNonNull(left, "left is null");
+ this.right = requireNonNull(right, "right is null");
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public Relation getLeft() {
+ return left;
+ }
+
+ public Relation getRight() {
+ return right;
+ }
+
+ public Optional<JoinCriteria> getCriteria() {
+ return Optional.ofNullable(criteria);
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitJoin(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ ImmutableList.Builder<Node> nodes = ImmutableList.builder();
+ nodes.add(left);
+ nodes.add(right);
+ if (criteria != null) {
+ nodes.addAll(criteria.getNodes());
+ }
+ return nodes.build();
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("type", type)
+ .add("left", left)
+ .add("right", right)
+ .add("criteria", criteria)
+ .omitNullValues()
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if ((o == null) || (getClass() != o.getClass())) {
+ return false;
+ }
+ Join join = (Join) o;
+ return (type == join.type) &&
+ Objects.equals(left, join.left) &&
+ Objects.equals(right, join.right) &&
+ Objects.equals(criteria, join.criteria);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, left, right, criteria);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ return type.equals(((Join) other).type);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/JoinCriteria.java
similarity index 69%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/JoinCriteria.java
index b61b0bbb9cd..155998839bc 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/JoinCriteria.java
@@ -19,24 +19,19 @@
package org.apache.iotdb.db.relational.sql.tree;
-import com.google.common.collect.ImmutableList;
-
-import javax.annotation.Nullable;
-
import java.util.List;
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
- super(location);
- }
+public abstract class JoinCriteria {
+ // Force subclasses to have a proper equals and hashcode implementation
@Override
- public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
- }
+ public abstract boolean equals(Object obj);
@Override
- public List<Node> getChildren() {
- return ImmutableList.of();
- }
+ public abstract int hashCode();
+
+ @Override
+ public abstract String toString();
+
+ public abstract List<Node> getNodes();
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/JoinOn.java
similarity index 52%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/JoinOn.java
index b61b0bbb9cd..7be2c93decb 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/JoinOn.java
@@ -21,22 +21,50 @@ package org.apache.iotdb.db.relational.sql.tree;
import com.google.common.collect.ImmutableList;
-import javax.annotation.Nullable;
-
import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static java.util.Objects.requireNonNull;
+
+public class JoinOn extends JoinCriteria {
+
+ private final Expression expression;
+
+ public JoinOn(Expression expression) {
+ this.expression = requireNonNull(expression, "expression is null");
+ }
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
- super(location);
+ public Expression getExpression() {
+ return expression;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (getClass() != obj.getClass())) {
+ return false;
+ }
+ JoinOn o = (JoinOn) obj;
+ return Objects.equals(expression, o.expression);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(expression);
}
@Override
- public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
+ public String toString() {
+ return toStringHelper(this)
+ .addValue(expression)
+ .toString();
}
@Override
- public List<Node> getChildren() {
- return ImmutableList.of();
+ public List<Node> getNodes() {
+ return ImmutableList.of(expression);
}
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/JoinUsing.java
similarity index 50%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/JoinUsing.java
index b61b0bbb9cd..0e560d6d403 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/JoinUsing.java
@@ -21,22 +21,52 @@ package org.apache.iotdb.db.relational.sql.tree;
import com.google.common.collect.ImmutableList;
-import javax.annotation.Nullable;
-
import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class JoinUsing extends JoinCriteria {
+ private final List<Identifier> columns;
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
- super(location);
+ public JoinUsing(List<Identifier> columns) {
+ requireNonNull(columns, "columns is null");
+ checkArgument(!columns.isEmpty(), "columns is empty");
+ this.columns = ImmutableList.copyOf(columns);
+ }
+
+ public List<Identifier> getColumns() {
+ return columns;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ JoinUsing o = (JoinUsing) obj;
+ return Objects.equals(columns, o.columns);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(columns);
}
@Override
- public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
+ public String toString() {
+ return toStringHelper(this)
+ .addValue(columns)
+ .toString();
}
@Override
- public List<Node> getChildren() {
+ public List<Node> getNodes() {
return ImmutableList.of();
}
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/LikePredicate.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/LikePredicate.java
new file mode 100644
index 00000000000..66fd2798278
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/LikePredicate.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import javax.annotation.Nullable;
+
+import static java.util.Objects.requireNonNull;
+
+public class LikePredicate extends Expression {
+
+ private final Expression value;
+ private final Expression pattern;
+ @Nullable
+ private final Expression escape;
+
+ public LikePredicate(Expression value, Expression pattern, Expression
escape) {
+ super(null);
+ this.value = requireNonNull(value, "value is null");
+ this.pattern = requireNonNull(pattern, "pattern is null");
+ this.escape = requireNonNull(escape, "escape is null");
+ }
+
+ public LikePredicate(NodeLocation location, Expression value, Expression
pattern) {
+ super(requireNonNull(location, "location is null"));
+ this.value = requireNonNull(value, "value is null");
+ this.pattern = requireNonNull(pattern, "pattern is null");
+ this.escape = null;
+ }
+
+ public Expression getValue() {
+ return value;
+ }
+
+ public Expression getPattern() {
+ return pattern;
+ }
+
+ public Optional<Expression> getEscape() {
+ return Optional.ofNullable(escape);
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitLikePredicate(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ ImmutableList.Builder<Node> result = ImmutableList.<Node>builder()
+ .add(value)
+ .add(pattern);
+
+ if (escape != null) {
+ result.add(escape);
+ }
+
+ return result.build();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ LikePredicate that = (LikePredicate) o;
+ return Objects.equals(value, that.value) &&
+ Objects.equals(pattern, that.pattern) &&
+ Objects.equals(escape, that.escape);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(value, pattern, escape);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Limit.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Limit.java
new file mode 100644
index 00000000000..c554e03ba19
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Limit.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class Limit extends Node {
+ private final Expression rowCount;
+
+ public Limit(Expression rowCount) {
+ super(null);
+ checkArgument(
+ rowCount instanceof AllRows ||
+ rowCount instanceof LongLiteral ||
+ rowCount instanceof Parameter,
+ "unexpected rowCount class: %s",
+ rowCount.getClass().getSimpleName());
+ this.rowCount = rowCount;
+ }
+
+ public Limit(NodeLocation location, Expression rowCount) {
+ super(requireNonNull(location, "location is null"));
+ checkArgument(
+ rowCount instanceof AllRows ||
+ rowCount instanceof LongLiteral ||
+ rowCount instanceof Parameter,
+ "unexpected rowCount class: %s",
+ rowCount.getClass().getSimpleName());
+ this.rowCount = rowCount;
+ }
+
+ public Expression getRowCount() {
+ return rowCount;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitLimit(this, context);
+ }
+
+ @Override
+ public List<? extends Node> getChildren() {
+ return ImmutableList.of(rowCount);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (getClass() != obj.getClass())) {
+ return false;
+ }
+ Limit o = (Limit) obj;
+ return Objects.equals(rowCount, o.rowCount);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(rowCount);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("limit", rowCount)
+ .toString();
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
index b61b0bbb9cd..5e6e582c725 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
@@ -21,9 +21,8 @@ package org.apache.iotdb.db.relational.sql.tree;
import com.google.common.collect.ImmutableList;
-import javax.annotation.Nullable;
-
import java.util.List;
+import javax.annotation.Nullable;
public abstract class Literal extends Expression {
protected Literal(@Nullable NodeLocation location) {
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/LogicalExpression.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/LogicalExpression.java
new file mode 100644
index 00000000000..efda0e5c1ae
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/LogicalExpression.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class LogicalExpression extends Expression {
+
+ public enum Operator {
+ AND, OR;
+
+ public Operator flip() {
+ if (this == AND) {
+ return OR;
+ } else if (this == OR) {
+ return AND;
+ } else {
+ throw new IllegalArgumentException("Unsupported logical expression
type: " + this);
+ }
+ }
+ }
+
+ private final Operator operator;
+ private final List<Expression> terms;
+
+ public LogicalExpression(Operator operator, List<Expression> terms) {
+ super(null);
+ this.operator = requireNonNull(operator, "operator is null");
+ checkArgument(terms.size() >= 2, "Expected at least 2 terms");
+ this.terms = ImmutableList.copyOf(terms);
+ }
+
+ public LogicalExpression(NodeLocation location, Operator operator,
List<Expression> terms) {
+ super(requireNonNull(location, "location is null"));
+ this.operator = requireNonNull(operator, "operator is null");
+ checkArgument(terms.size() >= 2, "Expected at least 2 terms");
+ this.terms = ImmutableList.copyOf(terms);
+ }
+
+ public Operator getOperator() {
+ return operator;
+ }
+
+ public List<Expression> getTerms() {
+ return terms;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitLogicalExpression(this, context);
+ }
+
+ @Override
+ public List<? extends Node> getChildren() {
+ return terms;
+ }
+
+ public static LogicalExpression and(Expression left, Expression right) {
+ return new LogicalExpression(Operator.AND, ImmutableList.of(left, right));
+ }
+
+ public static LogicalExpression or(Expression left, Expression right) {
+ return new LogicalExpression(Operator.OR, ImmutableList.of(left, right));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ LogicalExpression that = (LogicalExpression) o;
+ return operator == that.operator && Objects.equals(terms, that.terms);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(operator, terms);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ return operator == ((LogicalExpression) other).operator;
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/LongLiteral.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/LongLiteral.java
new file mode 100644
index 00000000000..88472eb1f25
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/LongLiteral.java
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import org.apache.iotdb.db.relational.sql.parser.ParsingException;
+
+import static java.util.Objects.requireNonNull;
+
+public class LongLiteral extends Literal {
+
+ private final String value;
+ private final long parsedValue;
+
+ public LongLiteral(String value) {
+ super(null);
+ try {
+ this.value = value;
+ this.parsedValue = parse(value);
+ } catch (NumberFormatException e) {
+ throw new ParsingException("Invalid numeric literal: " + value);
+ }
+ }
+
+ public LongLiteral(NodeLocation location, String value) {
+ super(requireNonNull(location, "location is null"));
+ try {
+ this.value = value;
+ this.parsedValue = parse(value);
+ } catch (NumberFormatException e) {
+ throw new ParsingException("Invalid numeric literal: " + value,
location);
+ }
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public long getParsedValue() {
+ return parsedValue;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitLongLiteral(this, context);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ LongLiteral that = (LongLiteral) o;
+
+ if (parsedValue != that.parsedValue) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) (parsedValue ^ (parsedValue >>> 32));
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ return parsedValue == ((LongLiteral) other).parsedValue;
+ }
+
+ private static long parse(String value) {
+ value = value.replace("_", "");
+
+ if (value.startsWith("0x") || value.startsWith("0X")) {
+ return Long.parseLong(value.substring(2), 16);
+ } else if (value.startsWith("0b") || value.startsWith("0B")) {
+ return Long.parseLong(value.substring(2), 2);
+ } else if (value.startsWith("0o") || value.startsWith("0O")) {
+ return Long.parseLong(value.substring(2), 8);
+ } else {
+ return Long.parseLong(value);
+ }
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NaturalJoin.java
similarity index 71%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NaturalJoin.java
index b61b0bbb9cd..3cb6d405077 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NaturalJoin.java
@@ -21,22 +21,31 @@ package org.apache.iotdb.db.relational.sql.tree;
import com.google.common.collect.ImmutableList;
-import javax.annotation.Nullable;
-
import java.util.List;
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
- super(location);
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+public class NaturalJoin extends JoinCriteria {
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ return (obj != null) && (getClass() == obj.getClass());
+ }
+
+ @Override
+ public int hashCode() {
+ return getClass().hashCode();
}
@Override
- public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
+ public String toString() {
+ return toStringHelper(this).toString();
}
@Override
- public List<Node> getChildren() {
+ public List<Node> getNodes() {
return ImmutableList.of();
}
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Node.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Node.java
index 96797b308f3..7c86b9bc0bd 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Node.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Node.java
@@ -61,7 +61,7 @@ public abstract class Node {
throw new UnsupportedOperationException("not yet implemented: " +
getClass().getName());
}
- static boolean sameClass(Node left, Node right) {
+ public static boolean sameClass(Node left, Node right) {
if (left == right) {
return true;
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NotExpression.java
similarity index 50%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NotExpression.java
index b61b0bbb9cd..dd425122c9a 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NotExpression.java
@@ -21,22 +21,59 @@ package org.apache.iotdb.db.relational.sql.tree;
import com.google.common.collect.ImmutableList;
-import javax.annotation.Nullable;
-
import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class NotExpression extends Expression {
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
- super(location);
+ private final Expression value;
+
+ public NotExpression(Expression value) {
+ super(null);
+ this.value = requireNonNull(value, "value is null");
+ }
+
+ public NotExpression(NodeLocation location, Expression value) {
+ super(requireNonNull(location, "location is null"));
+ this.value = requireNonNull(value, "value is null");
+ }
+
+ public Expression getValue() {
+ return value;
}
@Override
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
+ return visitor.visitNotExpression(this, context);
}
@Override
public List<Node> getChildren() {
- return ImmutableList.of();
+ return ImmutableList.of(value);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ NotExpression that = (NotExpression) o;
+ return Objects.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
}
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NullLiteral.java
similarity index 60%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NullLiteral.java
index b61b0bbb9cd..167cd54ddc8 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/NullLiteral.java
@@ -19,24 +19,42 @@
package org.apache.iotdb.db.relational.sql.tree;
-import com.google.common.collect.ImmutableList;
+import static java.util.Objects.requireNonNull;
-import javax.annotation.Nullable;
+public class NullLiteral extends Literal {
-import java.util.List;
+ public NullLiteral() {
+ super(null);
+ }
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
- super(location);
+ public NullLiteral(NodeLocation location) {
+ super(requireNonNull(location, "location is null"));
}
@Override
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
+ return visitor.visitNullLiteral(this, context);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return getClass().hashCode();
}
@Override
- public List<Node> getChildren() {
- return ImmutableList.of();
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
}
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Offset.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Offset.java
new file mode 100644
index 00000000000..888e263bda4
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Offset.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class Offset extends Node {
+
+ private final Expression rowCount;
+
+ public Offset(Expression rowCount) {
+ super(null);
+ checkArgument(rowCount instanceof LongLiteral || rowCount instanceof
Parameter,
+ "unexpected rowCount class: %s",
+ rowCount.getClass().getSimpleName());
+ this.rowCount = rowCount;
+ }
+
+ public Offset(NodeLocation location, Expression rowCount) {
+ super(requireNonNull(location, "location is null"));
+
+ checkArgument(rowCount instanceof LongLiteral || rowCount instanceof
Parameter,
+ "unexpected rowCount class: %s",
+ rowCount.getClass().getSimpleName());
+ this.rowCount = rowCount;
+ }
+
+ public Expression getRowCount() {
+ return rowCount;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitOffset(this, context);
+ }
+
+ @Override
+ public List<? extends Node> getChildren() {
+ return ImmutableList.of(rowCount);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (getClass() != obj.getClass())) {
+ return false;
+ }
+ Offset o = (Offset) obj;
+ return Objects.equals(rowCount, o.rowCount);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(rowCount);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("rowCount", rowCount)
+ .toString();
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/OrderBy.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/OrderBy.java
new file mode 100644
index 00000000000..952806d3e84
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/OrderBy.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class OrderBy extends Node {
+
+ private final List<SortItem> sortItems;
+
+ public OrderBy(List<SortItem> sortItems) {
+ super(null);
+ requireNonNull(sortItems, "sortItems is null");
+ checkArgument(!sortItems.isEmpty(), "sortItems should not be empty");
+ this.sortItems = ImmutableList.copyOf(sortItems);
+ }
+
+ public OrderBy(NodeLocation location, List<SortItem> sortItems) {
+ super(requireNonNull(location, "location is null"));
+ requireNonNull(sortItems, "sortItems is null");
+ checkArgument(!sortItems.isEmpty(), "sortItems should not be empty");
+ this.sortItems = ImmutableList.copyOf(sortItems);
+ }
+
+ public List<SortItem> getSortItems() {
+ return sortItems;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitOrderBy(this, context);
+ }
+
+ @Override
+ public List<? extends Node> getChildren() {
+ return sortItems;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("sortItems", sortItems)
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (getClass() != obj.getClass())) {
+ return false;
+ }
+ OrderBy o = (OrderBy) obj;
+ return Objects.equals(sortItems, o.sortItems);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(sortItems);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Parameter.java
similarity index 54%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Parameter.java
index b61b0bbb9cd..ce2dd025b35 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Parameter.java
@@ -21,22 +21,62 @@ package org.apache.iotdb.db.relational.sql.tree;
import com.google.common.collect.ImmutableList;
-import javax.annotation.Nullable;
-
import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class Parameter extends Expression {
+ private final int id;
+
+ public Parameter(int id) {
+ super(null);
+ this.id = id;
+ }
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
- super(location);
+ public Parameter(NodeLocation location, int id) {
+ super(requireNonNull(location, "location is null"));
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
}
@Override
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
+ return visitor.visitParameter(this, context);
}
@Override
public List<Node> getChildren() {
return ImmutableList.of();
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Parameter that = (Parameter) o;
+ return Objects.equals(id, that.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return id;
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ return id == ((Parameter) other).id;
+ }
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QuantifiedComparisonExpression.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QuantifiedComparisonExpression.java
new file mode 100644
index 00000000000..c6ec38a87d8
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QuantifiedComparisonExpression.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class QuantifiedComparisonExpression extends Expression {
+
+ public enum Quantifier {
+ ALL,
+ ANY,
+ SOME,
+ }
+
+ private final ComparisonExpression.Operator operator;
+ private final Quantifier quantifier;
+ private final Expression value;
+ private final Expression subquery;
+
+ public QuantifiedComparisonExpression(ComparisonExpression.Operator
operator, Quantifier quantifier, Expression value,
+ Expression subquery) {
+ super(null);
+ this.operator = requireNonNull(operator, "operator is null");
+ this.quantifier = requireNonNull(quantifier, "quantifier is null");
+ this.value = requireNonNull(value, "value is null");
+ this.subquery = requireNonNull(subquery, "subquery is null");
+ }
+
+ public QuantifiedComparisonExpression(NodeLocation location,
ComparisonExpression.Operator operator,
+ Quantifier quantifier, Expression
value, Expression subquery) {
+ super(requireNonNull(location, "location is null"));
+ this.operator = requireNonNull(operator, "operator is null");
+ this.quantifier = requireNonNull(quantifier, "quantifier is null");
+ this.value = requireNonNull(value, "value is null");
+ this.subquery = requireNonNull(subquery, "subquery is null");
+ }
+
+ public ComparisonExpression.Operator getOperator() {
+ return operator;
+ }
+
+ public Quantifier getQuantifier() {
+ return quantifier;
+ }
+
+ public Expression getValue() {
+ return value;
+ }
+
+ public Expression getSubquery() {
+ return subquery;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitQuantifiedComparisonExpression(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ return ImmutableList.of(value, subquery);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ QuantifiedComparisonExpression that = (QuantifiedComparisonExpression) o;
+ return operator == that.operator &&
+ quantifier == that.quantifier &&
+ Objects.equals(value, that.value) &&
+ Objects.equals(subquery, that.subquery);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(operator, quantifier, value, subquery);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ QuantifiedComparisonExpression otherNode =
(QuantifiedComparisonExpression) other;
+ return operator == otherNode.operator && quantifier ==
otherNode.quantifier;
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Query.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Query.java
new file mode 100644
index 00000000000..016e2846c42
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Query.java
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class Query extends Statement {
+
+ private final Optional<With> with;
+ private final QueryBody queryBody;
+ private final Optional<OrderBy> orderBy;
+ private final Optional<Offset> offset;
+ private final Optional<Node> limit;
+
+ public Query(
+ Optional<With> with,
+ QueryBody queryBody,
+ Optional<OrderBy> orderBy,
+ Optional<Offset> offset,
+ Optional<Node> limit) {
+ this(Optional.empty(), with, queryBody, orderBy, offset, limit);
+ }
+
+ public Query(
+ NodeLocation location,
+ Optional<With> with,
+ QueryBody queryBody,
+ Optional<OrderBy> orderBy,
+ Optional<Offset> offset,
+ Optional<Node> limit) {
+ this(Optional.of(location), with, queryBody, orderBy, offset, limit);
+ }
+
+ private Query(
+ Optional<NodeLocation> location,
+ Optional<With> with,
+ QueryBody queryBody,
+ Optional<OrderBy> orderBy,
+ Optional<Offset> offset,
+ Optional<Node> limit) {
+ super(location);
+ requireNonNull(with, "with is null");
+ requireNonNull(queryBody, "queryBody is null");
+ requireNonNull(orderBy, "orderBy is null");
+ requireNonNull(offset, "offset is null");
+ requireNonNull(limit, "limit is null");
+ checkArgument(!limit.isPresent() || limit.get() instanceof FetchFirst ||
limit.get() instanceof Limit,
+ "limit must be optional of either FetchFirst or Limit type");
+
+ this.with = with;
+ this.queryBody = queryBody;
+ this.orderBy = orderBy;
+ this.offset = offset;
+ this.limit = limit;
+ }
+
+ public Optional<With> getWith() {
+ return with;
+ }
+
+ public QueryBody getQueryBody() {
+ return queryBody;
+ }
+
+ public Optional<OrderBy> getOrderBy() {
+ return orderBy;
+ }
+
+ public Optional<Offset> getOffset() {
+ return offset;
+ }
+
+ public Optional<Node> getLimit() {
+ return limit;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitQuery(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ ImmutableList.Builder<Node> nodes = ImmutableList.builder();
+ nodes.addAll(functions);
+ with.ifPresent(nodes::add);
+ nodes.add(queryBody);
+ orderBy.ifPresent(nodes::add);
+ offset.ifPresent(nodes::add);
+ limit.ifPresent(nodes::add);
+ return nodes.build();
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("functions", functions.isEmpty() ? null : functions)
+ .add("with", with.orElse(null))
+ .add("queryBody", queryBody)
+ .add("orderBy", orderBy)
+ .add("offset", offset.orElse(null))
+ .add("limit", limit.orElse(null))
+ .omitNullValues()
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (getClass() != obj.getClass())) {
+ return false;
+ }
+ Query o = (Query) obj;
+ return Objects.equals(functions, o.functions) &&
+ Objects.equals(with, o.with) &&
+ Objects.equals(queryBody, o.queryBody) &&
+ Objects.equals(orderBy, o.orderBy) &&
+ Objects.equals(offset, o.offset) &&
+ Objects.equals(limit, o.limit);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(functions, with, queryBody, orderBy, offset, limit);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
+ }
+
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QueryBody.java
similarity index 76%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QueryBody.java
index b61b0bbb9cd..4ccfd29f6f6 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QueryBody.java
@@ -19,24 +19,17 @@
package org.apache.iotdb.db.relational.sql.tree;
-import com.google.common.collect.ImmutableList;
-
import javax.annotation.Nullable;
-import java.util.List;
+public abstract class QueryBody extends Relation {
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
+ protected QueryBody(@Nullable NodeLocation location) {
super(location);
}
@Override
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
+ return visitor.visitQueryBody(this, context);
}
- @Override
- public List<Node> getChildren() {
- return ImmutableList.of();
- }
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QuerySpecification.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QuerySpecification.java
new file mode 100644
index 00000000000..55b91452064
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/QuerySpecification.java
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class QuerySpecification extends QueryBody {
+
+ private final Select select;
+ private final Optional<Relation> from;
+ private final Optional<Expression> where;
+ private final Optional<GroupBy> groupBy;
+ private final Optional<Expression> having;
+ private final Optional<OrderBy> orderBy;
+ private final Optional<Offset> offset;
+ private final Optional<Node> limit;
+
+ public QuerySpecification(
+ Select select,
+ Optional<Relation> from,
+ Optional<Expression> where,
+ Optional<GroupBy> groupBy,
+ Optional<Expression> having,
+ Optional<OrderBy> orderBy,
+ Optional<Offset> offset,
+ Optional<Node> limit) {
+ this(Optional.empty(), select, from, where, groupBy, having, orderBy,
offset, limit);
+ }
+
+ public QuerySpecification(
+ NodeLocation location,
+ Select select,
+ Optional<Relation> from,
+ Optional<Expression> where,
+ Optional<GroupBy> groupBy,
+ Optional<Expression> having,
+ Optional<OrderBy> orderBy,
+ Optional<Offset> offset,
+ Optional<Node> limit) {
+ this(Optional.of(location), select, from, where, groupBy, having, orderBy,
offset, limit);
+ }
+
+ private QuerySpecification(
+ Optional<NodeLocation> location,
+ Select select,
+ Optional<Relation> from,
+ Optional<Expression> where,
+ Optional<GroupBy> groupBy,
+ Optional<Expression> having,
+ Optional<OrderBy> orderBy,
+ Optional<Offset> offset,
+ Optional<Limit> limit) {
+ super(location);
+ requireNonNull(select, "select is null");
+ requireNonNull(from, "from is null");
+ requireNonNull(where, "where is null");
+ requireNonNull(groupBy, "groupBy is null");
+ requireNonNull(having, "having is null");
+ requireNonNull(orderBy, "orderBy is null");
+ requireNonNull(offset, "offset is null");
+ requireNonNull(limit, "limit is null");
+
+ this.select = select;
+ this.from = from;
+ this.where = where;
+ this.groupBy = groupBy;
+ this.having = having;
+ this.orderBy = orderBy;
+ this.offset = offset;
+ this.limit = limit;
+ }
+
+ public Select getSelect() {
+ return select;
+ }
+
+ public Optional<Relation> getFrom() {
+ return from;
+ }
+
+ public Optional<Expression> getWhere() {
+ return where;
+ }
+
+ public Optional<GroupBy> getGroupBy() {
+ return groupBy;
+ }
+
+ public Optional<Expression> getHaving() {
+ return having;
+ }
+
+ public List<WindowDefinition> getWindows() {
+ return windows;
+ }
+
+ public Optional<OrderBy> getOrderBy() {
+ return orderBy;
+ }
+
+ public Optional<Offset> getOffset() {
+ return offset;
+ }
+
+ public Optional<Node> getLimit() {
+ return limit;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitQuerySpecification(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ ImmutableList.Builder<Node> nodes = ImmutableList.builder();
+ nodes.add(select);
+ from.ifPresent(nodes::add);
+ where.ifPresent(nodes::add);
+ groupBy.ifPresent(nodes::add);
+ having.ifPresent(nodes::add);
+ nodes.addAll(windows);
+ orderBy.ifPresent(nodes::add);
+ offset.ifPresent(nodes::add);
+ limit.ifPresent(nodes::add);
+ return nodes.build();
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("select", select)
+ .add("from", from)
+ .add("where", where.orElse(null))
+ .add("groupBy", groupBy)
+ .add("having", having.orElse(null))
+ .add("windows", windows.isEmpty() ? null : windows)
+ .add("orderBy", orderBy)
+ .add("offset", offset.orElse(null))
+ .add("limit", limit.orElse(null))
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (getClass() != obj.getClass())) {
+ return false;
+ }
+ QuerySpecification o = (QuerySpecification) obj;
+ return Objects.equals(select, o.select) &&
+ Objects.equals(from, o.from) &&
+ Objects.equals(where, o.where) &&
+ Objects.equals(groupBy, o.groupBy) &&
+ Objects.equals(having, o.having) &&
+ Objects.equals(windows, o.windows) &&
+ Objects.equals(orderBy, o.orderBy) &&
+ Objects.equals(offset, o.offset) &&
+ Objects.equals(limit, o.limit);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(select, from, where, groupBy, having, windows,
orderBy, offset, limit);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Relation.java
similarity index 73%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Relation.java
index b61b0bbb9cd..964a1b82efb 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Relation.java
@@ -19,24 +19,14 @@
package org.apache.iotdb.db.relational.sql.tree;
-import com.google.common.collect.ImmutableList;
+public abstract class Relation extends Node {
-import javax.annotation.Nullable;
-
-import java.util.List;
-
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
+ protected Relation(NodeLocation location) {
super(location);
}
@Override
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
- }
-
- @Override
- public List<Node> getChildren() {
- return ImmutableList.of();
+ return visitor.visitRelation(this, context);
}
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SearchedCaseExpression.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SearchedCaseExpression.java
new file mode 100644
index 00000000000..c047cdf94d1
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SearchedCaseExpression.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import javax.annotation.Nullable;
+
+import static java.util.Objects.requireNonNull;
+
+public class SearchedCaseExpression extends Expression {
+ private final List<WhenClause> whenClauses;
+ @Nullable
+ private final Expression defaultValue;
+
+ public SearchedCaseExpression(List<WhenClause> whenClauses) {
+ super(null);
+ this.whenClauses = ImmutableList.copyOf(requireNonNull(whenClauses,
"whenClauses is null"));
+ this.defaultValue = null;
+ }
+
+ public SearchedCaseExpression(List<WhenClause> whenClauses, Expression
defaultValue) {
+ super(null);
+ this.whenClauses = ImmutableList.copyOf(requireNonNull(whenClauses,
"whenClauses is null"));
+ this.defaultValue = requireNonNull(defaultValue, "defaultValue is null");
+ }
+
+ public SearchedCaseExpression(NodeLocation location, List<WhenClause>
whenClauses) {
+ super(requireNonNull(location, "location is null"));
+ this.whenClauses = ImmutableList.copyOf(requireNonNull(whenClauses,
"whenClauses is null"));
+ this.defaultValue = null;
+ }
+
+ public SearchedCaseExpression(NodeLocation location, List<WhenClause>
whenClauses, Expression defaultValue) {
+ super(requireNonNull(location, "location is null"));
+ this.whenClauses = ImmutableList.copyOf(requireNonNull(whenClauses,
"whenClauses is null"));
+ this.defaultValue = requireNonNull(defaultValue, "defaultValue is null");
+ }
+
+ public List<WhenClause> getWhenClauses() {
+ return whenClauses;
+ }
+
+ public Optional<Expression> getDefaultValue() {
+ return Optional.ofNullable(defaultValue);
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitSearchedCaseExpression(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ ImmutableList.Builder<Node> nodes = ImmutableList.builder();
+ nodes.addAll(whenClauses);
+ if (defaultValue != null) {
+ nodes.add(defaultValue);
+ }
+ return nodes.build();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ SearchedCaseExpression that = (SearchedCaseExpression) o;
+ return Objects.equals(whenClauses, that.whenClauses) &&
+ Objects.equals(defaultValue, that.defaultValue);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(whenClauses, defaultValue);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SimpleCaseExpression.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SimpleCaseExpression.java
new file mode 100644
index 00000000000..48fd0024903
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SimpleCaseExpression.java
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import javax.annotation.Nullable;
+
+import static java.util.Objects.requireNonNull;
+
+public class SimpleCaseExpression extends Expression {
+
+ private final Expression operand;
+ private final List<WhenClause> whenClauses;
+ @Nullable
+ private final Expression defaultValue;
+
+ public SimpleCaseExpression(Expression operand, List<WhenClause>
whenClauses) {
+ super(null);
+ this.operand = requireNonNull(operand, "operand is null");
+ this.whenClauses = ImmutableList.copyOf(requireNonNull(whenClauses,
"whenClauses is null"));
+ this.defaultValue = null;
+ }
+
+ public SimpleCaseExpression(Expression operand, List<WhenClause>
whenClauses, Expression defaultValue) {
+ super(null);
+ this.operand = requireNonNull(operand, "operand is null");
+ this.whenClauses = ImmutableList.copyOf(requireNonNull(whenClauses,
"whenClauses is null"));
+ this.defaultValue = requireNonNull(defaultValue, "defaultValue is null");
+ }
+
+ public SimpleCaseExpression(NodeLocation location, Expression operand,
List<WhenClause> whenClauses) {
+ super(requireNonNull(location, "location is null"));
+ this.operand = requireNonNull(operand, "operand is null");
+ this.whenClauses = ImmutableList.copyOf(requireNonNull(whenClauses,
"whenClauses is null"));
+ this.defaultValue = null;
+ }
+
+ public SimpleCaseExpression(NodeLocation location, Expression operand,
List<WhenClause> whenClauses,
+ Expression defaultValue) {
+ super(requireNonNull(location, "location is null"));
+ this.operand = requireNonNull(operand, "operand is null");
+ this.whenClauses = ImmutableList.copyOf(requireNonNull(whenClauses,
"whenClauses is null"));
+ this.defaultValue = requireNonNull(defaultValue, "defaultValue is null");
+ }
+
+ public Expression getOperand() {
+ return operand;
+ }
+
+ public List<WhenClause> getWhenClauses() {
+ return whenClauses;
+ }
+
+ public Optional<Expression> getDefaultValue() {
+ return Optional.ofNullable(defaultValue);
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitSimpleCaseExpression(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ ImmutableList.Builder<Node> nodes = ImmutableList.builder();
+ nodes.add(operand);
+ nodes.addAll(whenClauses);
+ if (defaultValue != null) {
+ nodes.add(defaultValue);
+ }
+ return nodes.build();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ SimpleCaseExpression that = (SimpleCaseExpression) o;
+ return Objects.equals(operand, that.operand) &&
+ Objects.equals(whenClauses, that.whenClauses) &&
+ Objects.equals(defaultValue, that.defaultValue);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(operand, whenClauses, defaultValue);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SortItem.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SortItem.java
new file mode 100644
index 00000000000..d7bafd583d9
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SortItem.java
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static java.util.Objects.requireNonNull;
+
+public class SortItem extends Node {
+
+ public enum Ordering {
+ ASCENDING, DESCENDING
+ }
+
+ public enum NullOrdering {
+ FIRST, LAST, UNDEFINED
+ }
+
+ private final Expression sortKey;
+ private final Ordering ordering;
+ private final NullOrdering nullOrdering;
+
+ public SortItem(Expression sortKey, Ordering ordering, NullOrdering
nullOrdering) {
+ super(null);
+ this.ordering = ordering;
+ this.sortKey = sortKey;
+ this.nullOrdering = nullOrdering;
+ }
+
+ public SortItem(NodeLocation location, Expression sortKey, Ordering
ordering, NullOrdering nullOrdering) {
+ super(requireNonNull(location, "location is null"));
+ this.ordering = ordering;
+ this.sortKey = sortKey;
+ this.nullOrdering = nullOrdering;
+ }
+
+ public Expression getSortKey() {
+ return sortKey;
+ }
+
+ public Ordering getOrdering() {
+ return ordering;
+ }
+
+ public NullOrdering getNullOrdering() {
+ return nullOrdering;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitSortItem(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ return ImmutableList.of(sortKey);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("sortKey", sortKey)
+ .add("ordering", ordering)
+ .add("nullOrdering", nullOrdering)
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ SortItem sortItem = (SortItem) o;
+ return Objects.equals(sortKey, sortItem.sortKey) &&
+ (ordering == sortItem.ordering) &&
+ (nullOrdering == sortItem.nullOrdering);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(sortKey, ordering, nullOrdering);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ SortItem otherItem = (SortItem) other;
+ return ordering == otherItem.ordering && nullOrdering ==
otherItem.nullOrdering;
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/StringLiteral.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/StringLiteral.java
new file mode 100644
index 00000000000..f5012f36995
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/StringLiteral.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class StringLiteral extends Literal {
+
+ private final String value;
+ private final int length;
+
+ public StringLiteral(String value) {
+ super(null);
+ this.value = requireNonNull(value, "value is null");
+ this.length = value.codePointCount(0, value.length());
+ }
+
+ public StringLiteral(NodeLocation location, String value) {
+ super(requireNonNull(location, "location is null"));
+ this.value = requireNonNull(value, "value is null");
+ this.length = value.codePointCount(0, value.length());
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public int length() {
+ return length;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitStringLiteral(this, context);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ StringLiteral that = (StringLiteral) o;
+ return Objects.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ return Objects.equals(value, ((StringLiteral) other).value);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SubqueryExpression.java
similarity index 50%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SubqueryExpression.java
index b61b0bbb9cd..6b6d0a8b8b3 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SubqueryExpression.java
@@ -21,22 +21,59 @@ package org.apache.iotdb.db.relational.sql.tree;
import com.google.common.collect.ImmutableList;
-import javax.annotation.Nullable;
-
import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class SubqueryExpression extends Expression {
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
- super(location);
+ private final Query query;
+
+ public SubqueryExpression(Query query) {
+ super(null);
+ this.query = requireNonNull(query, "query is null");
+ }
+
+ public SubqueryExpression(NodeLocation location, Query query) {
+ super(requireNonNull(location, "location is null"));
+ this.query = requireNonNull(query, "query is null");
+ }
+
+ public Query getQuery() {
+ return query;
}
@Override
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
+ return visitor.visitSubqueryExpression(this, context);
}
@Override
public List<Node> getChildren() {
- return ImmutableList.of();
+ return ImmutableList.of(query);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ SubqueryExpression that = (SubqueryExpression) o;
+ return Objects.equals(query, that.query);
+ }
+
+ @Override
+ public int hashCode() {
+ return query.hashCode();
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
}
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SymbolReference.java
similarity index 63%
copy from
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
copy to
iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SymbolReference.java
index b61b0bbb9cd..3d93a0dd33e 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Literal.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/SymbolReference.java
@@ -21,22 +21,46 @@ package org.apache.iotdb.db.relational.sql.tree;
import com.google.common.collect.ImmutableList;
-import javax.annotation.Nullable;
-
import java.util.List;
+import java.util.Objects;
+
+public class SymbolReference extends Expression {
+
+ private final String name;
-public abstract class Literal extends Expression {
- protected Literal(@Nullable NodeLocation location) {
- super(location);
+ public SymbolReference(String name) {
+ super(null);
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
}
@Override
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
- return visitor.visitLiteral(this, context);
+ return visitor.visitSymbolReference(this, context);
}
@Override
public List<Node> getChildren() {
return ImmutableList.of();
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ SymbolReference that = (SymbolReference) o;
+ return Objects.equals(name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Trim.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Trim.java
new file mode 100644
index 00000000000..56ce66db797
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Trim.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import javax.annotation.Nullable;
+
+import static java.util.Objects.requireNonNull;
+
+public class Trim extends Expression {
+ private final Specification specification;
+ private final Expression trimSource;
+ @Nullable
+ private final Expression trimCharacter;
+
+ public Trim(Specification specification, Expression trimSource) {
+ super(null);
+ this.specification = requireNonNull(specification, "specification is
null");
+ this.trimSource = requireNonNull(trimSource, "trimSource is null");
+ this.trimCharacter = null;
+ }
+
+ public Trim(Specification specification, Expression trimSource, Expression
trimCharacter) {
+ super(null);
+ this.specification = requireNonNull(specification, "specification is
null");
+ this.trimSource = requireNonNull(trimSource, "trimSource is null");
+ this.trimCharacter = requireNonNull(trimCharacter, "trimCharacter is
null");
+ }
+
+ public Trim(NodeLocation location, Specification specification, Expression
trimSource) {
+ super(requireNonNull(location, "location is null"));
+ this.specification = requireNonNull(specification, "specification is
null");
+ this.trimSource = requireNonNull(trimSource, "trimSource is null");
+ this.trimCharacter = null;
+ }
+
+ public Trim(NodeLocation location, Specification specification, Expression
trimSource, Expression trimCharacter) {
+ super(requireNonNull(location, "location is null"));
+ this.specification = requireNonNull(specification, "specification is
null");
+ this.trimSource = requireNonNull(trimSource, "trimSource is null");
+ this.trimCharacter = requireNonNull(trimCharacter, "trimCharacter is
null");
+ }
+
+ public Specification getSpecification() {
+ return specification;
+ }
+
+ public Expression getTrimSource() {
+ return trimSource;
+ }
+
+ public Optional<Expression> getTrimCharacter() {
+ return Optional.ofNullable(trimCharacter);
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitTrim(this, context);
+ }
+
+ @Override
+ public List<? extends Node> getChildren() {
+ ImmutableList.Builder<Node> nodes = ImmutableList.builder();
+ nodes.add(trimSource);
+ if (trimCharacter != null) {
+ nodes.add(trimCharacter);
+ }
+ return nodes.build();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Trim that = (Trim) o;
+ return specification == that.specification &&
+ Objects.equals(trimSource, that.trimSource) &&
+ Objects.equals(trimCharacter, that.trimCharacter);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(specification, trimSource, trimCharacter);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ Trim otherTrim = (Trim) other;
+ return specification == otherTrim.specification;
+ }
+
+ public enum Specification {
+ BOTH("trim"),
+ LEADING("ltrim"),
+ TRAILING("rtrim");
+
+ private final String functionName;
+
+ Specification(String functionName) {
+ this.functionName = requireNonNull(functionName, "functionName is null");
+ }
+
+ public String getFunctionName() {
+ return functionName;
+ }
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/WhenClause.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/WhenClause.java
new file mode 100644
index 00000000000..d2668c4ae88
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/WhenClause.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class WhenClause extends Expression {
+
+ private final Expression operand;
+ private final Expression result;
+
+ public WhenClause(Expression operand, Expression result) {
+ super(null);
+ this.operand = requireNonNull(operand, "operand is null");
+ this.result = requireNonNull(result, "result is null");
+ }
+
+ public WhenClause(NodeLocation location, Expression operand, Expression
result) {
+ super(requireNonNull(location, "location is null"));
+ this.operand = requireNonNull(operand, "operand is null");
+ this.result = requireNonNull(result, "result is null");
+ }
+
+ public Expression getOperand() {
+ return operand;
+ }
+
+ public Expression getResult() {
+ return result;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitWhenClause(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ return ImmutableList.of(operand, result);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ WhenClause that = (WhenClause) o;
+ return Objects.equals(operand, that.operand) &&
+ Objects.equals(result, that.result);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(operand, result);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/With.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/With.java
new file mode 100644
index 00000000000..9b68fee7b9d
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/With.java
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class With extends Node {
+
+ private final boolean recursive;
+ private final List<WithQuery> queries;
+
+ public With(boolean recursive, List<WithQuery> queries) {
+ super(null);
+
+ requireNonNull(queries, "queries is null");
+ checkArgument(!queries.isEmpty(), "queries is empty");
+
+ this.recursive = recursive;
+ this.queries = ImmutableList.copyOf(queries);
+ }
+
+ public With(NodeLocation location, boolean recursive, List<WithQuery>
queries) {
+ super(requireNonNull(location, "location is null"));
+
+ requireNonNull(queries, "queries is null");
+ checkArgument(!queries.isEmpty(), "queries is empty");
+
+ this.recursive = recursive;
+ this.queries = ImmutableList.copyOf(queries);
+ }
+
+ public boolean isRecursive() {
+ return recursive;
+ }
+
+ public List<WithQuery> getQueries() {
+ return queries;
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitWith(this, context);
+ }
+
+ @Override
+ public List<? extends Node> getChildren() {
+ return queries;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (getClass() != obj.getClass())) {
+ return false;
+ }
+ With o = (With) obj;
+ return Objects.equals(recursive, o.recursive) &&
+ Objects.equals(queries, o.queries);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(recursive, queries);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("recursive", recursive)
+ .add("queries", queries)
+ .toString();
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ return sameClass(this, other);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/WithQuery.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/WithQuery.java
new file mode 100644
index 00000000000..a92e19f9e20
--- /dev/null
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/WithQuery.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+package org.apache.iotdb.db.relational.sql.tree;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import javax.annotation.Nullable;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static java.util.Objects.requireNonNull;
+
+public class WithQuery extends Node {
+
+ private final Identifier name;
+ private final Query query;
+
+ @Nullable
+ private final List<Identifier> columnNames;
+
+ public WithQuery(Identifier name, Query query) {
+ super(null);
+ this.name = name;
+ this.query = requireNonNull(query, "query is null");
+ this.columnNames = null;
+ }
+
+ public WithQuery(Identifier name, Query query, List<Identifier> columnNames)
{
+ super(null);
+ this.name = name;
+ this.query = requireNonNull(query, "query is null");
+ this.columnNames = requireNonNull(columnNames, "columnNames is null");
+ }
+
+ public WithQuery(NodeLocation location, Identifier name, Query query) {
+ super(requireNonNull(location, "location is null"));
+ this.name = name;
+ this.query = requireNonNull(query, "query is null");
+ this.columnNames = null;
+ }
+
+ public WithQuery(NodeLocation location, Identifier name, Query query,
List<Identifier> columnNames) {
+ super(requireNonNull(location, "location is null"));
+ this.name = name;
+ this.query = requireNonNull(query, "query is null");
+ this.columnNames = requireNonNull(columnNames, "columnNames is null");
+ }
+
+ public Identifier getName() {
+ return name;
+ }
+
+ public Query getQuery() {
+ return query;
+ }
+
+ public Optional<List<Identifier>> getColumnNames() {
+ return Optional.ofNullable(columnNames);
+ }
+
+ @Override
+ public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+ return visitor.visitWithQuery(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ return ImmutableList.of(query);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("name", name)
+ .add("query", query)
+ .add("columnNames", columnNames)
+ .omitNullValues()
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, query, columnNames);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (getClass() != obj.getClass())) {
+ return false;
+ }
+ WithQuery o = (WithQuery) obj;
+ return Objects.equals(name, o.name) &&
+ Objects.equals(query, o.query) &&
+ Objects.equals(columnNames, o.columnNames);
+ }
+
+ @Override
+ public boolean shallowEquals(Node other) {
+ if (!sameClass(this, other)) {
+ return false;
+ }
+
+ WithQuery otherRelation = (WithQuery) other;
+ return name.equals(otherRelation.name) && Objects.equals(columnNames,
otherRelation.columnNames);
+ }
+}
diff --git
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/util/ExpressionFormatter.java
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/util/ExpressionFormatter.java
index de9ac00e13c..d2fe0cc7e5c 100644
---
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/util/ExpressionFormatter.java
+++
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/util/ExpressionFormatter.java
@@ -21,6 +21,8 @@ package org.apache.iotdb.db.relational.sql.util;
import org.apache.iotdb.db.relational.sql.tree.AstVisitor;
import org.apache.iotdb.db.relational.sql.tree.Expression;
+import org.apache.iotdb.db.relational.sql.tree.Literal;
+import org.apache.iotdb.db.relational.sql.tree.SymbolReference;
import java.util.Optional;
import java.util.function.Function;