This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new c41d23c47 [core] Sort some system table query result (#4306)
c41d23c47 is described below
commit c41d23c47fd96fe2b1df131ccea7f8e82f45b53b
Author: askwang <[email protected]>
AuthorDate: Fri Oct 11 15:52:04 2024 +0800
[core] Sort some system table query result (#4306)
---
.../apache/paimon/table/system/BucketsTable.java | 30 +++++---
.../paimon/table/system/PartitionsTable.java | 27 ++++---
.../org/apache/paimon/table/system/TagsTable.java | 4 +-
.../apache/paimon/table/system/TagsTableTest.java | 12 +++-
.../paimon/spark/sql/PaimonSystemTableTest.scala | 84 ++++++++++++++++++++++
5 files changed, 137 insertions(+), 20 deletions(-)
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/system/BucketsTable.java
b/paimon-core/src/main/java/org/apache/paimon/table/system/BucketsTable.java
index 0ac424850..ccc260ef0 100644
--- a/paimon-core/src/main/java/org/apache/paimon/table/system/BucketsTable.java
+++ b/paimon-core/src/main/java/org/apache/paimon/table/system/BucketsTable.java
@@ -40,6 +40,7 @@ import org.apache.paimon.types.DataField;
import org.apache.paimon.types.DataTypes;
import org.apache.paimon.types.RowType;
import org.apache.paimon.utils.IteratorRecordReader;
+import org.apache.paimon.utils.Pair;
import org.apache.paimon.utils.ProjectedRow;
import org.apache.paimon.utils.RowDataToObjectArrayConverter;
import org.apache.paimon.utils.SerializationUtils;
@@ -52,9 +53,11 @@ import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import static org.apache.paimon.catalog.Catalog.SYSTEM_TABLE_SPLITTER;
@@ -181,9 +184,24 @@ public class BucketsTable implements ReadonlyTable {
new RowDataToObjectArrayConverter(
fileStoreTable.schema().logicalPartitionType());
+ // sorted by partition and bucket
+ List<Pair<String, BucketEntry>> bucketList =
+ buckets.stream()
+ .map(
+ entry ->
+ Pair.of(
+ Arrays.toString(
+
converter.convert(entry.partition())),
+ entry))
+ .sorted(
+ Comparator.comparing(
+ (Pair<String, BucketEntry>
p) -> p.getLeft())
+ .thenComparing(p ->
p.getRight().bucket()))
+ .collect(Collectors.toList());
+
List<InternalRow> results = new ArrayList<>(buckets.size());
- for (BucketEntry entry : buckets) {
- results.add(toRow(entry, converter));
+ for (Pair<String, BucketEntry> pair : bucketList) {
+ results.add(toRow(pair.getLeft(), pair.getRight()));
}
Iterator<InternalRow> iterator = results.iterator();
@@ -198,13 +216,9 @@ public class BucketsTable implements ReadonlyTable {
return new IteratorRecordReader<>(iterator);
}
- private GenericRow toRow(
- BucketEntry entry, RowDataToObjectArrayConverter
partitionConverter) {
- BinaryString partitionId =
- BinaryString.fromString(
-
Arrays.toString(partitionConverter.convert(entry.partition())));
+ private GenericRow toRow(String partStr, BucketEntry entry) {
return GenericRow.of(
- partitionId,
+ BinaryString.fromString(partStr),
entry.bucket(),
entry.recordCount(),
entry.fileSizeInBytes(),
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/system/PartitionsTable.java
b/paimon-core/src/main/java/org/apache/paimon/table/system/PartitionsTable.java
index 5e966eabd..736347b9a 100644
---
a/paimon-core/src/main/java/org/apache/paimon/table/system/PartitionsTable.java
+++
b/paimon-core/src/main/java/org/apache/paimon/table/system/PartitionsTable.java
@@ -40,6 +40,7 @@ import org.apache.paimon.types.DataField;
import org.apache.paimon.types.DataTypes;
import org.apache.paimon.types.RowType;
import org.apache.paimon.utils.IteratorRecordReader;
+import org.apache.paimon.utils.Pair;
import org.apache.paimon.utils.ProjectedRow;
import org.apache.paimon.utils.RowDataToObjectArrayConverter;
import org.apache.paimon.utils.SerializationUtils;
@@ -53,9 +54,11 @@ import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import static org.apache.paimon.catalog.Catalog.SYSTEM_TABLE_SPLITTER;
@@ -181,9 +184,21 @@ public class PartitionsTable implements ReadonlyTable {
new RowDataToObjectArrayConverter(
fileStoreTable.schema().logicalPartitionType());
+ // sorted by partition
+ List<Pair<String, PartitionEntry>> partitionList =
+ partitions.stream()
+ .map(
+ entry ->
+ Pair.of(
+ Arrays.toString(
+
converter.convert(entry.partition())),
+ entry))
+ .sorted(Comparator.comparing(Pair::getLeft))
+ .collect(Collectors.toList());
+
List<InternalRow> results = new ArrayList<>(partitions.size());
- for (PartitionEntry entry : partitions) {
- results.add(toRow(entry, converter));
+ for (Pair<String, PartitionEntry> pair : partitionList) {
+ results.add(toRow(pair.getLeft(), pair.getRight()));
}
Iterator<InternalRow> iterator = results.iterator();
@@ -198,13 +213,9 @@ public class PartitionsTable implements ReadonlyTable {
return new IteratorRecordReader<>(iterator);
}
- private GenericRow toRow(
- PartitionEntry entry, RowDataToObjectArrayConverter
partitionConverter) {
- BinaryString partitionId =
- BinaryString.fromString(
-
Arrays.toString(partitionConverter.convert(entry.partition())));
+ private GenericRow toRow(String partStr, PartitionEntry entry) {
return GenericRow.of(
- partitionId,
+ BinaryString.fromString(partStr),
entry.recordCount(),
entry.fileSizeInBytes(),
entry.fileCount(),
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/system/TagsTable.java
b/paimon-core/src/main/java/org/apache/paimon/table/system/TagsTable.java
index abce3f330..dd7335e38 100644
--- a/paimon-core/src/main/java/org/apache/paimon/table/system/TagsTable.java
+++ b/paimon-core/src/main/java/org/apache/paimon/table/system/TagsTable.java
@@ -59,11 +59,11 @@ import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.TreeMap;
import static org.apache.paimon.catalog.Catalog.SYSTEM_TABLE_SPLITTER;
@@ -220,7 +220,7 @@ public class TagsTable implements ReadonlyTable {
LeafPredicate predicate = ((TagsSplit) split).tagName;
TagManager tagManager = new TagManager(fileIO, location, branch);
- Map<String, Tag> nameToSnapshot = new LinkedHashMap<>();
+ Map<String, Tag> nameToSnapshot = new TreeMap<>();
if (predicate != null
&& predicate.function() instanceof Equal
diff --git
a/paimon-core/src/test/java/org/apache/paimon/table/system/TagsTableTest.java
b/paimon-core/src/test/java/org/apache/paimon/table/system/TagsTableTest.java
index 8f8029cde..7ee8cd53d 100644
---
a/paimon-core/src/test/java/org/apache/paimon/table/system/TagsTableTest.java
+++
b/paimon-core/src/test/java/org/apache/paimon/table/system/TagsTableTest.java
@@ -40,6 +40,8 @@ import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
import static org.assertj.core.api.Assertions.assertThat;
@@ -89,11 +91,12 @@ class TagsTableTest extends TableTestBase {
}
private List<InternalRow> getExpectedResult() {
- List<InternalRow> internalRows = new ArrayList<>();
+ Map<String, InternalRow> tagToRows = new TreeMap<>();
for (Pair<Tag, String> snapshot : tagManager.tagObjects()) {
Tag tag = snapshot.getKey();
String tagName = snapshot.getValue();
- internalRows.add(
+ tagToRows.put(
+ tagName,
GenericRow.of(
BinaryString.fromString(tagName),
tag.id(),
@@ -109,6 +112,11 @@ class TagsTableTest extends TableTestBase {
: BinaryString.fromString(
tag.getTagTimeRetained().toString())));
}
+
+ List<InternalRow> internalRows = new ArrayList<>();
+ for (Map.Entry<String, InternalRow> entry : tagToRows.entrySet()) {
+ internalRows.add(entry.getValue());
+ }
return internalRows;
}
}
diff --git
a/paimon-spark/paimon-spark-common/src/test/scala/org/apache/paimon/spark/sql/PaimonSystemTableTest.scala
b/paimon-spark/paimon-spark-common/src/test/scala/org/apache/paimon/spark/sql/PaimonSystemTableTest.scala
new file mode 100644
index 000000000..64baf6232
--- /dev/null
+++
b/paimon-spark/paimon-spark-common/src/test/scala/org/apache/paimon/spark/sql/PaimonSystemTableTest.scala
@@ -0,0 +1,84 @@
+/*
+ * 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.paimon.spark.sql
+
+import org.apache.paimon.spark.PaimonSparkTestBase
+
+import org.apache.spark.sql.Row
+
+class PaimonSystemTableTest extends PaimonSparkTestBase {
+
+ test("system table: sort tags table") {
+ spark.sql(s"""
+ |CREATE TABLE T (id STRING, name STRING)
+ |USING PAIMON
+ |""".stripMargin)
+
+ spark.sql(s"INSERT INTO T VALUES(1, 'a')")
+
+ spark.sql("CALL paimon.sys.create_tag(table => 'test.T', tag =>
'2024-10-02')")
+ spark.sql("CALL paimon.sys.create_tag(table => 'test.T', tag =>
'2024-10-01')")
+ spark.sql("CALL paimon.sys.create_tag(table => 'test.T', tag =>
'2024-10-04')")
+ spark.sql("CALL paimon.sys.create_tag(table => 'test.T', tag =>
'2024-10-03')")
+
+ checkAnswer(
+ spark.sql("select tag_name from `T$tags`"),
+ Row("2024-10-01") :: Row("2024-10-02") :: Row("2024-10-03") ::
Row("2024-10-04") :: Nil)
+ }
+
+ test("system table: sort partitions table") {
+ spark.sql(s"""
+ |CREATE TABLE T (a INT, b STRING,dt STRING,hh STRING)
+ |PARTITIONED BY (dt, hh)
+ |TBLPROPERTIES ('primary-key'='a,dt,hh', 'bucket' = '3')
+ |""".stripMargin)
+
+ spark.sql("INSERT INTO T VALUES(1, 'a', '2024-10-10', '01')")
+ spark.sql("INSERT INTO T VALUES(3, 'c', '2024-10-10', '23')")
+ spark.sql("INSERT INTO T VALUES(2, 'b', '2024-10-10', '12')")
+ spark.sql("INSERT INTO T VALUES(5, 'f', '2024-10-09', '02')")
+ spark.sql("INSERT INTO T VALUES(4, 'd', '2024-10-09', '01')")
+
+ checkAnswer(spark.sql("select count(*) from `T$partitions`"), Row(5) ::
Nil)
+ checkAnswer(
+ spark.sql("select partition from `T$partitions`"),
+ Row("[2024-10-09, 01]") :: Row("[2024-10-09, 02]") :: Row("[2024-10-10,
01]") :: Row(
+ "[2024-10-10, 12]") :: Row("[2024-10-10, 23]") :: Nil
+ )
+ }
+
+ test("system table: sort buckets table") {
+ spark.sql(s"""
+ |CREATE TABLE T (a INT, b STRING,dt STRING,hh STRING)
+ |PARTITIONED BY (dt, hh)
+ |TBLPROPERTIES ('primary-key'='a,dt,hh', 'bucket' = '3')
+ |""".stripMargin)
+
+ spark.sql("INSERT INTO T VALUES(1, 'a', '2024-10-10', '01')")
+ spark.sql("INSERT INTO T VALUES(2, 'b', '2024-10-10', '01')")
+ spark.sql("INSERT INTO T VALUES(3, 'c', '2024-10-10', '01')")
+ spark.sql("INSERT INTO T VALUES(4, 'd', '2024-10-10', '01')")
+ spark.sql("INSERT INTO T VALUES(5, 'f', '2024-10-10', '01')")
+
+ checkAnswer(spark.sql("select count(*) from `T$partitions`"), Row(1) ::
Nil)
+ checkAnswer(
+ spark.sql("select partition,bucket from `T$buckets`"),
+ Row("[2024-10-10, 01]", 0) :: Row("[2024-10-10, 01]", 1) ::
Row("[2024-10-10, 01]", 2) :: Nil)
+ }
+}