This is an automated email from the ASF dual-hosted git repository.

liuneng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-gluten.git


The following commit(s) were added to refs/heads/main by this push:
     new e9bff4f27f [CH] add test for new native parquet reader (#8797)
e9bff4f27f is described below

commit e9bff4f27f341570bec270e0f327e59484b737bf
Author: LiuNeng <[email protected]>
AuthorDate: Mon Feb 24 16:54:24 2025 +0800

    [CH] add test for new native parquet reader (#8797)
    
    What changes were proposed in this pull request?
    test new native parquet reader
    
    How was this patch tested?
    (Please explain how this patch was tested. E.g. unit tests, integration 
tests, manual tests)
    
    (If this patch involves UI changes, please attach a screenshot; otherwise, 
remove this)
---
 ...nClickHouseTPCHSaltNullNativeParquetSuite.scala | 359 +++++++++++++++++++++
 cpp-ch/clickhouse.version                          |   2 +-
 2 files changed, 360 insertions(+), 1 deletion(-)

diff --git 
a/backends-clickhouse/src/test/scala/org/apache/gluten/execution/tpch/GlutenClickHouseTPCHSaltNullNativeParquetSuite.scala
 
b/backends-clickhouse/src/test/scala/org/apache/gluten/execution/tpch/GlutenClickHouseTPCHSaltNullNativeParquetSuite.scala
new file mode 100644
index 0000000000..3e7847d876
--- /dev/null
+++ 
b/backends-clickhouse/src/test/scala/org/apache/gluten/execution/tpch/GlutenClickHouseTPCHSaltNullNativeParquetSuite.scala
@@ -0,0 +1,359 @@
+/*
+ * 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.gluten.execution.tpch
+
+import org.apache.gluten.backendsapi.clickhouse.{CHConfig, RuntimeSettings}
+import org.apache.gluten.execution._
+
+import org.apache.spark.SparkConf
+import org.apache.spark.sql.DataFrame
+import org.apache.spark.sql.catalyst.optimizer.BuildLeft
+import org.apache.spark.sql.functions.{col, rand, when}
+
+import java.io.File
+
+// Some sqls' line length exceeds 100
+// scalastyle:off line.size.limit
+
+class GlutenClickHouseTPCHSaltNullNativeParquetSuite extends 
GlutenClickHouseTPCHAbstractSuite {
+
+  override protected val needCopyParquetToTablePath = true
+
+  override protected val tablesPath: String = basePath + "/tpch-data"
+  override protected val tpchQueries: String =
+    rootPath + 
"../../../../tools/gluten-it/common/src/main/resources/tpch-queries"
+  override protected val queriesResults: String = rootPath + "queries-output"
+  val runtimeConfigPrefix = 
"spark.gluten.sql.columnar.backend.ch.runtime_config."
+
+  override protected def sparkConf: SparkConf = {
+    super.sparkConf
+      .set("spark.shuffle.manager", "sort")
+      .set("spark.io.compression.codec", "snappy")
+      .set("spark.sql.shuffle.partitions", "5")
+      .set("spark.sql.autoBroadcastJoinThreshold", "10MB")
+      .set("spark.gluten.supported.scala.udfs", "my_add")
+      .set(
+        
CHConfig.runtimeSettings("input_format_parquet_use_native_reader_with_filter_push_down"),
+        "true")
+  }
+
+  override protected val createNullableTables = true
+
+  override protected def createTPCHNullableTables(): Unit = {
+
+    // first process the parquet data to:
+    // 1. make every column nullable in schema (optional rather than required)
+    // 2. salt some null values randomly
+    val saltedTablesPath = tablesPath + "-salted"
+    withSQLConf(vanillaSparkConfs(): _*) {
+      Seq("customer", "lineitem", "nation", "orders", "part", "partsupp", 
"region", "supplier")
+        .map(
+          tableName => {
+            val originTablePath = tablesPath + "/" + tableName
+            val df = spark.read.parquet(originTablePath)
+            var salted_df: Option[DataFrame] = None
+            for (c <- df.schema) {
+              salted_df = Some((salted_df match {
+                case Some(x) => x
+                case None => df
+              }).withColumn(c.name, when(rand() < 0.01, 
null).otherwise(col(c.name))))
+            }
+
+            val currentSaltedTablePath = saltedTablesPath + "/" + tableName
+            val file = new File(currentSaltedTablePath)
+            if (file.exists()) {
+              file.delete()
+            }
+            salted_df.get.write.parquet(currentSaltedTablePath)
+          })
+    }
+
+    val customerData = saltedTablesPath + "/customer"
+    spark.sql(s"DROP TABLE IF EXISTS customer")
+    spark.sql(s"""
+                 | CREATE TABLE IF NOT EXISTS customer (
+                 | c_custkey    bigint,
+                 | c_name       string,
+                 | c_address    string,
+                 | c_nationkey  bigint,
+                 | c_phone      string,
+                 | c_acctbal    double,
+                 | c_mktsegment string,
+                 | c_comment    string)
+                 | USING PARQUET LOCATION '$customerData'
+                 |""".stripMargin)
+
+    val lineitemData = saltedTablesPath + "/lineitem"
+    spark.sql(s"DROP TABLE IF EXISTS lineitem")
+    spark.sql(s"""
+                 | CREATE TABLE IF NOT EXISTS lineitem (
+                 | l_orderkey      bigint,
+                 | l_partkey       bigint,
+                 | l_suppkey       bigint,
+                 | l_linenumber    bigint,
+                 | l_quantity      double,
+                 | l_extendedprice double,
+                 | l_discount      double,
+                 | l_tax           double,
+                 | l_returnflag    string,
+                 | l_linestatus    string,
+                 | l_shipdate      date,
+                 | l_commitdate    date,
+                 | l_receiptdate   date,
+                 | l_shipinstruct  string,
+                 | l_shipmode      string,
+                 | l_comment       string)
+                 | USING PARQUET LOCATION '$lineitemData'
+                 |""".stripMargin)
+
+    val nationData = saltedTablesPath + "/nation"
+    spark.sql(s"DROP TABLE IF EXISTS nation")
+    spark.sql(s"""
+                 | CREATE TABLE IF NOT EXISTS nation (
+                 | n_nationkey bigint,
+                 | n_name      string,
+                 | n_regionkey bigint,
+                 | n_comment   string)
+                 | USING PARQUET LOCATION '$nationData'
+                 |""".stripMargin)
+
+    val regionData = saltedTablesPath + "/region"
+    spark.sql(s"DROP TABLE IF EXISTS region")
+    spark.sql(s"""
+                 | CREATE TABLE IF NOT EXISTS region (
+                 | r_regionkey bigint,
+                 | r_name      string,
+                 | r_comment   string)
+                 | USING PARQUET LOCATION '$regionData'
+                 |""".stripMargin)
+
+    val ordersData = saltedTablesPath + "/orders"
+    spark.sql(s"DROP TABLE IF EXISTS orders")
+    spark.sql(s"""
+                 | CREATE TABLE IF NOT EXISTS orders (
+                 | o_orderkey      bigint,
+                 | o_custkey       bigint,
+                 | o_orderstatus   string,
+                 | o_totalprice    double,
+                 | o_orderdate     date,
+                 | o_orderpriority string,
+                 | o_clerk         string,
+                 | o_shippriority  bigint,
+                 | o_comment       string)
+                 | USING PARQUET LOCATION '$ordersData'
+                 |""".stripMargin)
+
+    val partData = saltedTablesPath + "/part"
+    spark.sql(s"DROP TABLE IF EXISTS part")
+    spark.sql(s"""
+                 | CREATE TABLE IF NOT EXISTS part (
+                 | p_partkey     bigint,
+                 | p_name        string,
+                 | p_mfgr        string,
+                 | p_brand       string,
+                 | p_type        string,
+                 | p_size        bigint,
+                 | p_container   string,
+                 | p_retailprice double,
+                 | p_comment     string)
+                 | USING PARQUET LOCATION '$partData'
+                 |""".stripMargin)
+
+    val partsuppData = saltedTablesPath + "/partsupp"
+    spark.sql(s"DROP TABLE IF EXISTS partsupp")
+    spark.sql(s"""
+                 | CREATE TABLE IF NOT EXISTS partsupp (
+                 | ps_partkey    bigint,
+                 | ps_suppkey    bigint,
+                 | ps_availqty   bigint,
+                 | ps_supplycost double,
+                 | ps_comment    string)
+                 | USING PARQUET LOCATION '$partsuppData'
+                 |""".stripMargin)
+
+    val supplierData = saltedTablesPath + "/supplier"
+    spark.sql(s"DROP TABLE IF EXISTS supplier")
+    spark.sql(s"""
+                 | CREATE TABLE IF NOT EXISTS supplier (
+                 | s_suppkey   bigint,
+                 | s_name      string,
+                 | s_address   string,
+                 | s_nationkey bigint,
+                 | s_phone     string,
+                 | s_acctbal   double,
+                 | s_comment   string)
+                 | USING PARQUET LOCATION '$supplierData'
+                 |""".stripMargin)
+
+    val result = spark
+      .sql(s"""
+              | show tables;
+              |""".stripMargin)
+      .collect()
+    assertResult(8)(result.length)
+  }
+
+  test("TPCH Q1") {
+    runTPCHQuery(1) {
+      df =>
+        val scanExec = df.queryExecution.executedPlan.collect {
+          case scanExec: BasicScanExecTransformer => true
+        }
+        assert(scanExec.size == 1)
+    }
+  }
+
+  test("TPCH Q2") {
+    runTPCHQuery(2) {
+      df =>
+        val scanExec = df.queryExecution.executedPlan.collect {
+          case scanExec: BasicScanExecTransformer => scanExec
+        }
+        assert(scanExec.size == 8)
+    }
+  }
+
+  test("TPCH Q3") {
+    withSQLConf(("spark.sql.autoBroadcastJoinThreshold", "-1")) {
+      runTPCHQuery(3) {
+        df =>
+          val shjBuildLeft = df.queryExecution.executedPlan.collect {
+            case shj: ShuffledHashJoinExecTransformerBase if shj.joinBuildSide 
== BuildLeft => shj
+          }
+          assert(shjBuildLeft.size == 1)
+      }
+    }
+  }
+
+  test("TPCH Q4") {
+    runTPCHQuery(4) { df => }
+  }
+
+  test("TPCH Q5") {
+    withSQLConf(("spark.sql.autoBroadcastJoinThreshold", "-1")) {
+      runTPCHQuery(5) {
+        df =>
+          val bhjRes = df.queryExecution.executedPlan.collect {
+            case bhj: BroadcastHashJoinExecTransformerBase => bhj
+          }
+          assert(bhjRes.isEmpty)
+      }
+    }
+  }
+
+  test("TPCH Q6") {
+    runTPCHQuery(6) { df => }
+  }
+
+  test("TPCH Q7") {
+    withSQLConf(
+      ("spark.sql.shuffle.partitions", "1"),
+      ("spark.sql.autoBroadcastJoinThreshold", "-1")) {
+      runTPCHQuery(7) { df => }
+    }
+  }
+
+  test("TPCH Q8") {
+    withSQLConf(
+      ("spark.sql.shuffle.partitions", "1"),
+      ("spark.sql.autoBroadcastJoinThreshold", "-1")) {
+      runTPCHQuery(8) { df => }
+    }
+  }
+
+  test("TPCH Q9") {
+    runTPCHQuery(9) { df => }
+  }
+
+  test("TPCH Q10") {
+    runTPCHQuery(10) { df => }
+  }
+
+  test("TPCH Q11") {
+    runTPCHQuery(11) { df => }
+  }
+
+  test("TPCH Q12") {
+    runTPCHQuery(12) { df => }
+  }
+
+  test("TPCH Q13") {
+    runTPCHQuery(13) { df => }
+  }
+
+  test("TPCH Q14") {
+    withSQLConf(
+      ("spark.sql.shuffle.partitions", "1"),
+      ("spark.sql.autoBroadcastJoinThreshold", "-1")) {
+      runTPCHQuery(14) { df => }
+    }
+  }
+
+  test("TPCH Q15") {
+    runTPCHQuery(15) { df => }
+  }
+
+  // see issue https://github.com/Kyligence/ClickHouse/issues/93
+  test("TPCH Q16") {
+    runTPCHQuery(16) { df => }
+  }
+
+  test("TPCH Q17") {
+    withSQLConf(("spark.shuffle.sort.bypassMergeThreshold", "2")) {
+      runTPCHQuery(17) { df => }
+    }
+  }
+
+  test("TPCH Q18") {
+    withSQLConf(("spark.shuffle.sort.bypassMergeThreshold", "2")) {
+      runTPCHQuery(18) { df => }
+    }
+  }
+
+  test("TPCH Q19") {
+    runTPCHQuery(19) { df => }
+  }
+
+  test("TPCH Q20") {
+    runTPCHQuery(20) { df => }
+  }
+
+  test("TPCH Q21") {
+    runTPCHQuery(21) { df => }
+  }
+
+  test("TPCH Q22") {
+    runTPCHQuery(22) { df => }
+  }
+
+  override protected def runTPCHQuery(
+      queryNum: Int,
+      tpchQueries: String = tpchQueries,
+      queriesResults: String = queriesResults,
+      compareResult: Boolean = true,
+      noFallBack: Boolean = true)(customCheck: DataFrame => Unit): Unit = {
+
+    withSQLConf((RuntimeSettings.COLLECT_METRICS.key, "false")) {
+      compareTPCHQueryAgainstVanillaSpark(queryNum, tpchQueries, customCheck, 
noFallBack)
+    }
+    withSQLConf((RuntimeSettings.COLLECT_METRICS.key, "true")) {
+      compareTPCHQueryAgainstVanillaSpark(queryNum, tpchQueries, customCheck, 
noFallBack)
+    }
+  }
+
+}
+// scalastyle:on line.size.limit
diff --git a/cpp-ch/clickhouse.version b/cpp-ch/clickhouse.version
index 89031ace1b..3bb393d0c3 100644
--- a/cpp-ch/clickhouse.version
+++ b/cpp-ch/clickhouse.version
@@ -1,3 +1,3 @@
 CH_ORG=Kyligence
 CH_BRANCH=rebase_ch/20250221
-CH_COMMIT=dfb7f9649ee
+CH_COMMIT=9371612100c129efca3f9a3eeb114c0beddf25c2


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to