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 875f5037eda fix compile
875f5037eda is described below

commit 875f5037eda5680945b8a8e60dd548343637f0d6
Author: JackieTien97 <[email protected]>
AuthorDate: Wed Feb 28 12:23:10 2024 +0800

    fix compile
---
 .../relational/analyzer/AggregationAnalyzer.java   |   6 +
 .../relational/analyzer/StatementAnalyzer.java     | 175 ++++++++++++---------
 .../db/relational/grammar/sql/RelationalSql.g4     |   2 +
 .../iotdb/db/relational/sql/parser/AstBuilder.java |   6 +
 .../iotdb/db/relational/sql/tree/AstVisitor.java   |   4 +
 .../sql/tree/DefaultTraversalVisitor.java          |   8 +
 .../apache/iotdb/db/relational/sql/tree/Row.java   |  77 +++++++++
 .../iotdb/tsfile/read/common/type/BinaryType.java  |  10 +-
 .../iotdb/tsfile/read/common/type/BooleanType.java |   8 +
 .../iotdb/tsfile/read/common/type/DoubleType.java  |   8 +
 .../iotdb/tsfile/read/common/type/FloatType.java   |  10 +-
 .../iotdb/tsfile/read/common/type/IntType.java     |  10 +-
 .../iotdb/tsfile/read/common/type/LongType.java    |  10 +-
 .../iotdb/tsfile/read/common/type/RowType.java     | 147 +++++++++++++++++
 .../apache/iotdb/tsfile/read/common/type/Type.java |   5 +
 .../iotdb/tsfile/read/common/type/TypeEnum.java    |   4 +-
 16 files changed, 409 insertions(+), 81 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AggregationAnalyzer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AggregationAnalyzer.java
index b1a642d95e5..48aa4ea7890 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AggregationAnalyzer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AggregationAnalyzer.java
@@ -48,6 +48,7 @@ import org.apache.iotdb.db.relational.sql.tree.NotExpression;
 import org.apache.iotdb.db.relational.sql.tree.NullIfExpression;
 import org.apache.iotdb.db.relational.sql.tree.Parameter;
 import org.apache.iotdb.db.relational.sql.tree.QuantifiedComparisonExpression;
+import org.apache.iotdb.db.relational.sql.tree.Row;
 import org.apache.iotdb.db.relational.sql.tree.SearchedCaseExpression;
 import org.apache.iotdb.db.relational.sql.tree.SimpleCaseExpression;
 import org.apache.iotdb.db.relational.sql.tree.SubqueryExpression;
@@ -418,6 +419,11 @@ class AggregationAnalyzer {
       return !node.getDefaultValue().isPresent() || 
process(node.getDefaultValue().get(), context);
     }
 
+    @Override
+    protected Boolean visitRow(Row node, Void context) {
+      return node.getItems().stream().allMatch(item -> process(item, context));
+    }
+
     @Override
     protected Boolean visitParameter(Parameter node, Void context) {
       //      if (analysis.isDescribe()) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
index 26a4d9b8c8c..89628784651 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
@@ -76,6 +76,7 @@ import 
org.apache.iotdb.db.relational.sql.tree.QuerySpecification;
 import org.apache.iotdb.db.relational.sql.tree.Relation;
 import org.apache.iotdb.db.relational.sql.tree.RenameColumn;
 import org.apache.iotdb.db.relational.sql.tree.RenameTable;
+import org.apache.iotdb.db.relational.sql.tree.Row;
 import org.apache.iotdb.db.relational.sql.tree.Select;
 import org.apache.iotdb.db.relational.sql.tree.SelectItem;
 import org.apache.iotdb.db.relational.sql.tree.SetOperation;
@@ -94,8 +95,10 @@ import org.apache.iotdb.db.relational.sql.tree.TableSubquery;
 import org.apache.iotdb.db.relational.sql.tree.Union;
 import org.apache.iotdb.db.relational.sql.tree.Update;
 import org.apache.iotdb.db.relational.sql.tree.Use;
+import org.apache.iotdb.db.relational.sql.tree.Values;
 import org.apache.iotdb.db.relational.sql.tree.With;
 import org.apache.iotdb.db.relational.sql.tree.WithQuery;
+import org.apache.iotdb.tsfile.read.common.type.RowType;
 import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import com.google.common.collect.ArrayListMultimap;
@@ -127,6 +130,7 @@ import static 
com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.ImmutableList.toImmutableList;
 import static com.google.common.collect.ImmutableSet.toImmutableSet;
 import static com.google.common.collect.Iterables.getLast;
+import static com.google.common.collect.Iterables.getOnlyElement;
 import static java.lang.Math.toIntExact;
 import static java.util.Collections.emptyList;
 import static java.util.Locale.ENGLISH;
@@ -1588,82 +1592,101 @@ public class StatementAnalyzer {
     // accessControlScope, filter));
     //    }
 
-    //    @Override
-    //    protected Scope visitValues(Values node, Optional<Scope> scope) {
-    //      checkState(!node.getRows().isEmpty());
-    //
-    //      List<Type> rowTypes = node.getRows().stream()
-    //          .map(row -> analyzeExpression(row, 
createScope(scope)).getType(row))
-    //          .map(type -> {
-    //            if (type instanceof RowType) {
-    //              return type;
-    //            }
-    //            return RowType.anonymousRow(type);
-    //          })
-    //          .collect(toImmutableList());
-    //
-    //      int fieldCount = rowTypes.get(0).getTypeParameters().size();
-    //      Type commonSuperType = rowTypes.get(0);
-    //      for (Type rowType : rowTypes) {
-    //        // check field count consistency for rows
-    //        if (rowType.getTypeParameters().size() != fieldCount) {
-    //          throw semanticException(TYPE_MISMATCH,
-    //              node,
-    //              "Values rows have mismatched sizes: %s vs %s",
-    //              fieldCount,
-    //              rowType.getTypeParameters().size());
-    //        }
-    //
-    //        // determine common super type of the rows
-    //        commonSuperType = typeCoercion.getCommonSuperType(rowType, 
commonSuperType)
-    //            .orElseThrow(() -> semanticException(TYPE_MISMATCH,
-    //                node,
-    //                "Values rows have mismatched types: %s vs %s",
-    //                rowTypes.get(0),
-    //                rowType));
-    //      }
-    //
-    //      // add coercions
-    //      for (Expression row : node.getRows()) {
-    //        Type actualType = analysis.getType(row);
-    //        if (row instanceof Row) {
-    //          // coerce Row by fields to preserve Row structure and enable 
optimizations based on
-    // this structure, e.g. pruning, predicate extraction
-    //          // TODO coerce the whole Row and add an Optimizer rule that 
converts CAST(ROW(...)
-    // AS ...) into ROW(CAST(...), CAST(...), ...).
-    //          //  The rule would also handle Row-type expressions that were 
specified as
-    // CAST(ROW). It should support multiple casts over a ROW.
-    //          for (int i = 0; i < actualType.getTypeParameters().size(); 
i++) {
-    //            Expression item = ((Row) row).getItems().get(i);
-    //            Type actualItemType = actualType.getTypeParameters().get(i);
-    //            Type expectedItemType = 
commonSuperType.getTypeParameters().get(i);
-    //            if (!actualItemType.equals(expectedItemType)) {
-    //              analysis.addCoercion(item, expectedItemType,
-    //                  typeCoercion.isTypeOnlyCoercion(actualItemType, 
expectedItemType));
-    //            }
-    //          }
-    //        } else if (actualType instanceof RowType) {
-    //          // coerce row-type expression as a whole
-    //          if (!actualType.equals(commonSuperType)) {
-    //            analysis.addCoercion(row, commonSuperType,
-    // typeCoercion.isTypeOnlyCoercion(actualType, commonSuperType));
-    //          }
-    //        } else {
-    //          // coerce field. it will be wrapped in Row by Planner
-    //          Type superType = 
getOnlyElement(commonSuperType.getTypeParameters());
-    //          if (!actualType.equals(superType)) {
-    //            analysis.addCoercion(row, superType, 
typeCoercion.isTypeOnlyCoercion(actualType,
-    // superType));
-    //          }
-    //        }
-    //      }
-    //
-    //      List<Field> fields = commonSuperType.getTypeParameters().stream()
-    //          .map(valueType -> Field.newUnqualified(Optional.empty(), 
valueType))
-    //          .collect(toImmutableList());
-    //
-    //      return createAndAssignScope(node, scope, fields);
-    //    }
+    @Override
+    protected Scope visitValues(Values node, Optional<Scope> scope) {
+      checkState(!node.getRows().isEmpty());
+
+      List<Type> rowTypes =
+          node.getRows().stream()
+              .map(row -> analyzeExpression(row, 
createScope(scope)).getType(row))
+              .map(
+                  type -> {
+                    if (type instanceof RowType) {
+                      return type;
+                    }
+                    return RowType.anonymousRow(type);
+                  })
+              .collect(toImmutableList());
+
+      int fieldCount = rowTypes.get(0).getTypeParameters().size();
+      Type commonSuperType = rowTypes.get(0);
+      for (Type rowType : rowTypes) {
+        // check field count consistency for rows
+        if (rowType.getTypeParameters().size() != fieldCount) {
+          throw new SemanticException(
+              String.format(
+                  "Values rows have mismatched sizes: %s vs %s",
+                  fieldCount, rowType.getTypeParameters().size()));
+        }
+
+        // determine common super type of the rows
+        //        commonSuperType = typeCoercion.getCommonSuperType(rowType, 
commonSuperType)
+        //            .orElseThrow(() -> semanticException(TYPE_MISMATCH,
+        //                node,
+        //                "Values rows have mismatched types: %s vs %s",
+        //                rowTypes.get(0),
+        //                rowType));
+      }
+
+      // add coercions
+      int rowIndex = 0;
+      for (Expression row : node.getRows()) {
+        Type actualType = analysis.getType(row);
+        if (row instanceof Row) {
+          // coerce Row by fields to preserve Row structure and enable 
optimizations based on this
+          // structure, e.g.pruning, predicate extraction
+          // TODO coerce the whole Row and add an Optimizer rule that converts 
CAST(ROW(...) AS
+          // ...)into ROW (CAST(...),CAST(...), ...).
+          //  The rule would also handle Row-type expressions that were 
specified as CAST(ROW).It
+          // should support multiple casts over a ROW.
+          for (int i = 0; i < actualType.getTypeParameters().size(); i++) {
+            //            Expression item = ((Row) row).getItems().get(i);
+            Type actualItemType = actualType.getTypeParameters().get(i);
+            Type expectedItemType = commonSuperType.getTypeParameters().get(i);
+            if (!actualItemType.equals(expectedItemType)) {
+              throw new SemanticException(
+                  String.format(
+                      "Type of row %d column %d is mismatched, expected: %s, 
actual: %s",
+                      rowIndex, i, expectedItemType, actualItemType));
+              //              analysis.addCoercion(item, expectedItemType,
+              //                  
typeCoercion.isTypeOnlyCoercion(actualItemType,
+              // expectedItemType));
+            }
+          }
+        } else if (actualType instanceof RowType) {
+          // coerce row-type expression as a whole
+          //          if (!actualType.equals(commonSuperType)) {
+          //            analysis.addCoercion(row, commonSuperType,
+          //                typeCoercion.isTypeOnlyCoercion(actualType, 
commonSuperType));
+          //          }
+
+          throw new SemanticException(
+              String.format(
+                  "Type of row %d is mismatched, expected: %s, actual: %s",
+                  rowIndex, commonSuperType, actualType));
+        } else {
+          // coerce field. it will be wrapped in Row by Planner
+          Type superType = getOnlyElement(commonSuperType.getTypeParameters());
+          if (!actualType.equals(superType)) {
+            //            analysis.addCoercion(row, superType,
+            // typeCoercion.isTypeOnlyCoercion(actualType,
+            //                superType));
+            throw new SemanticException(
+                String.format(
+                    "Type of row %d is mismatched, expected: %s, actual: %s",
+                    rowIndex, superType, actualType));
+          }
+        }
+        rowIndex++;
+      }
+
+      List<Field> fields =
+          commonSuperType.getTypeParameters().stream()
+              .map(valueType -> Field.newUnqualified(Optional.empty(), 
valueType))
+              .collect(toImmutableList());
+
+      return createAndAssignScope(node, scope, fields);
+    }
 
     @Override
     protected Scope visitAliasedRelation(AliasedRelation relation, 
Optional<Scope> scope) {
diff --git 
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
 
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
index 84e4fea8301..880ab455df7 100644
--- 
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
+++ 
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
@@ -543,6 +543,8 @@ valueExpression
 
 primaryExpression
     : literalExpression                                                        
           #literal
+    | '(' expression (',' expression)+ ')'                                     
           #rowConstructor
+    | ROW '(' expression (',' expression)* ')'                                 
           #rowConstructor
     | qualifiedName '(' (label=identifier '.')? ASTERISK ')'                   
           #functionCall
     | qualifiedName '(' (setQuantifier? expression (',' expression)*)?')'      
           #functionCall
     | '(' query ')'                                                            
           #subqueryExpression
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java
index 65ad32a3ef2..7fbc148ffdb 100644
--- 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/parser/AstBuilder.java
@@ -95,6 +95,7 @@ import 
org.apache.iotdb.db.relational.sql.tree.QuerySpecification;
 import org.apache.iotdb.db.relational.sql.tree.Relation;
 import org.apache.iotdb.db.relational.sql.tree.RenameColumn;
 import org.apache.iotdb.db.relational.sql.tree.RenameTable;
+import org.apache.iotdb.db.relational.sql.tree.Row;
 import org.apache.iotdb.db.relational.sql.tree.SearchedCaseExpression;
 import org.apache.iotdb.db.relational.sql.tree.Select;
 import org.apache.iotdb.db.relational.sql.tree.SelectItem;
@@ -1151,6 +1152,11 @@ public class AstBuilder extends 
RelationalSqlBaseVisitor<Node> {
     return visit(ctx.expression());
   }
 
+  @Override
+  public Node visitRowConstructor(RelationalSqlParser.RowConstructorContext 
context) {
+    return new Row(getLocation(context), visit(context.expression(), 
Expression.class));
+  }
+
   @Override
   public Node visitCast(RelationalSqlParser.CastContext ctx) {
     return new Cast(
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 553e4860f89..5622b964657 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
@@ -271,6 +271,10 @@ public abstract class AstVisitor<R, C> {
     return visitQueryBody(node, context);
   }
 
+  protected R visitRow(Row node, C context) {
+    return visitExpression(node, context);
+  }
+
   protected R visitTableSubquery(TableSubquery node, C context) {
     return visitQueryBody(node, context);
   }
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DefaultTraversalVisitor.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DefaultTraversalVisitor.java
index 8f0f19a4a12..51444fb7f3f 100644
--- 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DefaultTraversalVisitor.java
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/DefaultTraversalVisitor.java
@@ -333,6 +333,14 @@ public abstract class DefaultTraversalVisitor<C> extends 
AstVisitor<Void, C> {
     return null;
   }
 
+  @Override
+  protected Void visitRow(Row node, C context) {
+    for (Expression expression : node.getItems()) {
+      process(expression, context);
+    }
+    return null;
+  }
+
   @Override
   protected Void visitTableSubquery(TableSubquery node, C context) {
     process(node.getQuery(), context);
diff --git 
a/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Row.java
 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Row.java
new file mode 100644
index 00000000000..0e37061e81f
--- /dev/null
+++ 
b/iotdb-core/relational-parser/src/main/java/org/apache/iotdb/db/relational/sql/tree/Row.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 com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class Row extends Expression {
+  private final List<Expression> items;
+
+  public Row(List<Expression> items) {
+    super(null);
+    this.items = ImmutableList.copyOf(requireNonNull(items, "items is null"));
+  }
+
+  public Row(NodeLocation location, List<Expression> items) {
+    super(requireNonNull(location, "location is null"));
+    this.items = ImmutableList.copyOf(requireNonNull(items, "items is null"));
+  }
+
+  public List<Expression> getItems() {
+    return items;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitRow(this, context);
+  }
+
+  @Override
+  public List<? extends Node> getChildren() {
+    return items;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(items);
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null || getClass() != obj.getClass()) {
+      return false;
+    }
+    Row other = (Row) obj;
+    return Objects.equals(this.items, other.items);
+  }
+
+  @Override
+  public boolean shallowEquals(Node other) {
+    return sameClass(this, other);
+  }
+}
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java
index 98e988c38bc..19c9551942e 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java
@@ -24,8 +24,11 @@ import 
org.apache.iotdb.tsfile.read.common.block.column.Column;
 import org.apache.iotdb.tsfile.read.common.block.column.ColumnBuilder;
 import org.apache.iotdb.tsfile.utils.Binary;
 
+import java.util.Collections;
+import java.util.List;
+
 public class BinaryType implements Type {
-  private static final BinaryType TEXT = new BinaryType();
+  public static final BinaryType TEXT = new BinaryType();
 
   private BinaryType() {}
 
@@ -64,6 +67,11 @@ public class BinaryType implements Type {
     return true;
   }
 
+  @Override
+  public List<Type> getTypeParameters() {
+    return Collections.emptyList();
+  }
+
   public static BinaryType getInstance() {
     return TEXT;
   }
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BooleanType.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BooleanType.java
index fdb65f8d030..b86ee21f90d 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BooleanType.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BooleanType.java
@@ -23,6 +23,9 @@ import 
org.apache.iotdb.tsfile.read.common.block.column.BooleanColumnBuilder;
 import org.apache.iotdb.tsfile.read.common.block.column.Column;
 import org.apache.iotdb.tsfile.read.common.block.column.ColumnBuilder;
 
+import java.util.Collections;
+import java.util.List;
+
 public class BooleanType implements Type {
 
   public static final BooleanType BOOLEAN = new BooleanType();
@@ -64,6 +67,11 @@ public class BooleanType implements Type {
     return true;
   }
 
+  @Override
+  public List<Type> getTypeParameters() {
+    return Collections.emptyList();
+  }
+
   public static BooleanType getInstance() {
     return BOOLEAN;
   }
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/DoubleType.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/DoubleType.java
index 0d64ffef1b7..da4734e8a92 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/DoubleType.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/DoubleType.java
@@ -23,6 +23,9 @@ import 
org.apache.iotdb.tsfile.read.common.block.column.Column;
 import org.apache.iotdb.tsfile.read.common.block.column.ColumnBuilder;
 import org.apache.iotdb.tsfile.read.common.block.column.DoubleColumnBuilder;
 
+import java.util.Collections;
+import java.util.List;
+
 public class DoubleType implements Type {
 
   public static final DoubleType DOUBLE = new DoubleType();
@@ -94,6 +97,11 @@ public class DoubleType implements Type {
     return true;
   }
 
+  @Override
+  public List<Type> getTypeParameters() {
+    return Collections.emptyList();
+  }
+
   public static DoubleType getInstance() {
     return DOUBLE;
   }
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/FloatType.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/FloatType.java
index 96d258f533b..67a9b58be0e 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/FloatType.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/FloatType.java
@@ -23,9 +23,12 @@ import 
org.apache.iotdb.tsfile.read.common.block.column.Column;
 import org.apache.iotdb.tsfile.read.common.block.column.ColumnBuilder;
 import org.apache.iotdb.tsfile.read.common.block.column.FloatColumnBuilder;
 
+import java.util.Collections;
+import java.util.List;
+
 public class FloatType implements Type {
 
-  private static final FloatType FLOAT = new FloatType();
+  public static final FloatType FLOAT = new FloatType();
 
   private FloatType() {}
 
@@ -94,6 +97,11 @@ public class FloatType implements Type {
     return true;
   }
 
+  @Override
+  public List<Type> getTypeParameters() {
+    return Collections.emptyList();
+  }
+
   public static FloatType getInstance() {
     return FLOAT;
   }
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/IntType.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/IntType.java
index e0108f925d5..a793744e053 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/IntType.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/IntType.java
@@ -23,9 +23,12 @@ import 
org.apache.iotdb.tsfile.read.common.block.column.Column;
 import org.apache.iotdb.tsfile.read.common.block.column.ColumnBuilder;
 import org.apache.iotdb.tsfile.read.common.block.column.IntColumnBuilder;
 
+import java.util.Collections;
+import java.util.List;
+
 public class IntType implements Type {
 
-  private static final IntType INT32 = new IntType();
+  public static final IntType INT32 = new IntType();
 
   private IntType() {}
 
@@ -94,6 +97,11 @@ public class IntType implements Type {
     return true;
   }
 
+  @Override
+  public List<Type> getTypeParameters() {
+    return Collections.emptyList();
+  }
+
   public static IntType getInstance() {
     return INT32;
   }
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/LongType.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/LongType.java
index 383bc37619f..9ae2a9ccfb8 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/LongType.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/LongType.java
@@ -23,9 +23,12 @@ import 
org.apache.iotdb.tsfile.read.common.block.column.Column;
 import org.apache.iotdb.tsfile.read.common.block.column.ColumnBuilder;
 import org.apache.iotdb.tsfile.read.common.block.column.LongColumnBuilder;
 
+import java.util.Collections;
+import java.util.List;
+
 public class LongType implements Type {
 
-  private static final LongType INT64 = new LongType();
+  public static final LongType INT64 = new LongType();
 
   private LongType() {}
 
@@ -94,6 +97,11 @@ public class LongType implements Type {
     return true;
   }
 
+  @Override
+  public List<Type> getTypeParameters() {
+    return Collections.emptyList();
+  }
+
   public static LongType getInstance() {
     return INT64;
   }
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/RowType.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/RowType.java
new file mode 100644
index 00000000000..ad8b003169a
--- /dev/null
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/RowType.java
@@ -0,0 +1,147 @@
+/*
+ * 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.tsfile.read.common.type;
+
+import org.apache.iotdb.tsfile.read.common.block.column.ColumnBuilder;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static java.util.Objects.requireNonNull;
+import static org.apache.iotdb.tsfile.read.common.type.TypeEnum.ROW;
+
+public class RowType implements Type {
+
+  private final List<Field> fields;
+  private final List<Type> fieldTypes;
+  private final boolean comparable;
+  private final boolean orderable;
+
+  private RowType(List<Field> originalFields) {
+
+    this.fields = new ArrayList<>(originalFields);
+    this.fieldTypes = 
fields.stream().map(Field::getType).collect(Collectors.toList());
+
+    this.comparable = fields.stream().allMatch(field -> 
field.getType().isComparable());
+    this.orderable = fields.stream().allMatch(field -> 
field.getType().isOrderable());
+  }
+
+  public static RowType from(List<Field> fields) {
+    return new RowType(fields);
+  }
+
+  public static RowType anonymous(List<Type> types) {
+    List<Field> fields =
+        types.stream().map(type -> new Field(Optional.empty(), 
type)).collect(Collectors.toList());
+
+    return new RowType(fields);
+  }
+
+  public static RowType rowType(Field... field) {
+    return from(Arrays.asList(field));
+  }
+
+  public static RowType anonymousRow(Type... types) {
+    return anonymous(Arrays.asList(types));
+  }
+
+  // Only RowParametricType.createType should call this method
+  public static RowType createWithTypeSignature(List<Field> fields) {
+    return new RowType(fields);
+  }
+
+  public static Field field(String name, Type type) {
+    return new Field(Optional.of(name), type);
+  }
+
+  public static Field field(Type type) {
+    return new Field(Optional.empty(), type);
+  }
+
+  @Override
+  public ColumnBuilder createColumnBuilder(int expectedEntries) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public TypeEnum getTypeEnum() {
+    return ROW;
+  }
+
+  @Override
+  public String getDisplayName() {
+    // Convert to standard sql name
+    StringBuilder result = new StringBuilder();
+    result.append("ROW").append('(');
+    for (Field field : fields) {
+      String typeDisplayName = field.getType().getDisplayName();
+      if (field.getName().isPresent()) {
+        // TODO: names are already canonicalized, so they should be printed as 
delimited identifiers
+        result.append(field.getName().get()).append(' 
').append(typeDisplayName);
+      } else {
+        result.append(typeDisplayName);
+      }
+      result.append(", ");
+    }
+    result.setLength(result.length() - 2);
+    result.append(')');
+    return result.toString();
+  }
+
+  @Override
+  public List<Type> getTypeParameters() {
+    return fieldTypes;
+  }
+
+  public List<Field> getFields() {
+    return fields;
+  }
+
+  public static class Field {
+    private final Type type;
+    private final Optional<String> name;
+
+    public Field(Optional<String> name, Type type) {
+      this.type = requireNonNull(type, "type is null");
+      this.name = requireNonNull(name, "name is null");
+    }
+
+    public Type getType() {
+      return type;
+    }
+
+    public Optional<String> getName() {
+      return name;
+    }
+  }
+
+  @Override
+  public boolean isComparable() {
+    return comparable;
+  }
+
+  @Override
+  public boolean isOrderable() {
+    return orderable;
+  }
+}
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/Type.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/Type.java
index 1babec273aa..864663e96af 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/Type.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/Type.java
@@ -23,6 +23,8 @@ import 
org.apache.iotdb.tsfile.read.common.block.column.Column;
 import org.apache.iotdb.tsfile.read.common.block.column.ColumnBuilder;
 import org.apache.iotdb.tsfile.utils.Binary;
 
+import java.util.List;
+
 public interface Type {
 
   /** Gets a boolean at {@code position}. */
@@ -111,4 +113,7 @@ public interface Type {
 
   /** True if the type supports compareTo. */
   boolean isOrderable();
+
+  /** For parameterized types returns the list of parameters. */
+  List<Type> getTypeParameters();
 }
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
index 83b91495abd..eeacbb14817 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java
@@ -30,5 +30,7 @@ public enum TypeEnum {
 
   BOOLEAN,
 
-  BINARY
+  BINARY,
+
+  ROW
 }

Reply via email to