From bc710ab887e7814208025e54cfcab41ccdc65ef5 Mon Sep 17 00:00:00 2001 From: Kazantsev Maksim Date: Thu, 2 Oct 2025 22:03:32 +0400 Subject: [PATCH 1/6] bitmap_count draft impl --- native/core/src/execution/jni_api.rs | 2 + .../apache/comet/serde/QueryPlanSerde.scala | 10 ++++ .../org/apache/comet/serde/bitmaps.scala | 37 ++++++++++++ .../comet/CometBitmapExpressionSuite.scala | 59 +++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 spark/src/main/scala/org/apache/comet/serde/bitmaps.scala create mode 100644 spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala diff --git a/native/core/src/execution/jni_api.rs b/native/core/src/execution/jni_api.rs index 52b8eb6a30..bddfbc9652 100644 --- a/native/core/src/execution/jni_api.rs +++ b/native/core/src/execution/jni_api.rs @@ -40,6 +40,7 @@ use datafusion::{ prelude::{SessionConfig, SessionContext}, }; use datafusion_comet_proto::spark_operator::Operator; +use datafusion_spark::function::bitmap::bitmap_count::BitmapCount; use datafusion_spark::function::bitwise::bit_get::SparkBitGet; use datafusion_spark::function::datetime::date_add::SparkDateAdd; use datafusion_spark::function::datetime::date_sub::SparkDateSub; @@ -307,6 +308,7 @@ fn prepare_datafusion_session_context( session_ctx.register_udf(ScalarUDF::new_from_impl(SparkBitGet::default())); session_ctx.register_udf(ScalarUDF::new_from_impl(SparkDateAdd::default())); session_ctx.register_udf(ScalarUDF::new_from_impl(SparkDateSub::default())); + session_ctx.register_udf(ScalarUDF::new_from_impl(BitmapCount::default())); // Must be the last one to override existing functions with the same name datafusion_comet_spark_expr::register_all_comet_functions(&mut session_ctx)?; diff --git a/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala b/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala index 892d8bca63..d1504c35e7 100644 --- a/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala +++ b/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala @@ -845,6 +845,16 @@ object QueryPlanSerde extends Logging with CometExprShim { None } + case s: StaticInvoke + if s.staticObject == classOf[BitmapExpressionUtils] && + s.dataType.isInstanceOf[BinaryType] && + s.functionName == "bitmapCount" && + s.arguments.size == 1 => + val childProto = exprToProto(s.arguments.head, inputs, binding) + val bitmapCountScalarExpr = + scalarFunctionExprToProtoWithReturnType("bitmap_count", IntegerType, childProto) + optExprWithInfo(bitmapCountScalarExpr, expr, expr.children: _*) + case KnownFloatingPointNormalized(NormalizeNaNAndZero(expr)) => val dataType = serializeDataType(expr.dataType) if (dataType.isEmpty) { diff --git a/spark/src/main/scala/org/apache/comet/serde/bitmaps.scala b/spark/src/main/scala/org/apache/comet/serde/bitmaps.scala new file mode 100644 index 0000000000..1468e600d3 --- /dev/null +++ b/spark/src/main/scala/org/apache/comet/serde/bitmaps.scala @@ -0,0 +1,37 @@ +/* + * 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.comet.serde + +import org.apache.spark.sql.catalyst.expressions.{Attribute, BitmapCount} +import org.apache.spark.sql.types.IntegerType + +import org.apache.comet.serde.QueryPlanSerde.{exprToProto, optExprWithInfo, scalarFunctionExprToProtoWithReturnType} + +object CometBitmapCount extends CometExpressionSerde[BitmapCount] { + override def convert( + expr: BitmapCount, + inputs: Seq[Attribute], + binding: Boolean): Option[ExprOuterClass.Expr] = { + val childProto = exprToProto(expr.child, inputs, binding) + val bitmapCountScalarExpr = + scalarFunctionExprToProtoWithReturnType("bitmap_count", IntegerType, childProto) + optExprWithInfo(bitmapCountScalarExpr, expr, expr.children: _*) + } +} diff --git a/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala b/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala new file mode 100644 index 0000000000..b78a3c863b --- /dev/null +++ b/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala @@ -0,0 +1,59 @@ +/* + * 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.comet + +import scala.util.Random + +import org.apache.hadoop.fs.Path +import org.apache.spark.sql.CometTestBase +import org.apache.spark.sql.execution.adaptive.AdaptiveSparkPlanHelper + +import org.apache.comet.CometSparkSessionExtensions.isSpark35Plus +import org.apache.comet.testing.{DataGenOptions, ParquetGenerator} + +class CometBitmapExpressionSuite extends CometTestBase with AdaptiveSparkPlanHelper { + + test("bitmap_count") { + assume(isSpark35Plus) + withTempDir { dir => + val path = new Path(dir.toURI.toString, "test.parquet") + val filename = path.toString + val random = new Random(42) + withSQLConf(CometConf.COMET_ENABLED.key -> "false") { + ParquetGenerator.makeParquetFile( + random, + spark, + filename, + 100, + DataGenOptions( + allowNull = true, + generateNegativeZero = true, + generateArray = false, + generateStruct = false, + generateMap = false)) + } + val table = spark.read.parquet(filename) + table.createOrReplaceTempView("t1") + val df = sql("SELECT bitmap_count(c13) FROM t1") + df.explain(true) + checkSparkAnswerAndOperator(df) + } + } +} From 6947b3cfab1398be348e38843b6c10f3dcd7225a Mon Sep 17 00:00:00 2001 From: Kazantsev Maksim Date: Fri, 3 Oct 2025 22:03:43 +0400 Subject: [PATCH 2/6] bitmap_count draft impl --- .../apache/comet/serde/QueryPlanSerde.scala | 38 +------------- .../org/apache/comet/serde/statics.scala | 51 +++++++++++++++++++ .../comet/CometBitmapExpressionSuite.scala | 15 +++++- 3 files changed, 67 insertions(+), 37 deletions(-) create mode 100644 spark/src/main/scala/org/apache/comet/serde/statics.scala diff --git a/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala b/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala index d1504c35e7..a267bb2e1d 100644 --- a/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala +++ b/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala @@ -28,7 +28,6 @@ import org.apache.spark.sql.catalyst.expressions.aggregate._ import org.apache.spark.sql.catalyst.expressions.objects.StaticInvoke import org.apache.spark.sql.catalyst.optimizer.{BuildLeft, BuildRight, NormalizeNaNAndZero} import org.apache.spark.sql.catalyst.plans._ -import org.apache.spark.sql.catalyst.util.CharVarcharCodegenUtils import org.apache.spark.sql.catalyst.util.ResolveDefaultColumns.getExistenceDefaultValues import org.apache.spark.sql.comet._ import org.apache.spark.sql.comet.execution.shuffle.CometShuffleExchangeExec @@ -230,7 +229,8 @@ object QueryPlanSerde extends Logging with CometExprShim { classOf[Coalesce] -> CometCoalesce, classOf[Literal] -> CometLiteral, classOf[MonotonicallyIncreasingID] -> CometMonotonicallyIncreasingId, - classOf[SparkPartitionID] -> CometSparkPartitionId) + classOf[SparkPartitionID] -> CometSparkPartitionId, + classOf[StaticInvoke] -> CometStaticInvoke) /** * Mapping of Spark expression class to Comet expression handler. @@ -821,40 +821,6 @@ object QueryPlanSerde extends Logging with CometExprShim { None } - // With Spark 3.4, CharVarcharCodegenUtils.readSidePadding gets called to pad spaces for - // char types. - // See https://github.com/apache/spark/pull/38151 - case s: StaticInvoke - // classOf gets ther runtime class of T, which lets us compare directly - // Otherwise isInstanceOf[Class[T]] will always evaluate to true for Class[_] - if s.staticObject == classOf[CharVarcharCodegenUtils] && - s.dataType.isInstanceOf[StringType] && - s.functionName == "readSidePadding" && - s.arguments.size == 2 && - s.propagateNull && - !s.returnNullable && - s.isDeterministic => - val argsExpr = Seq( - exprToProtoInternal(Cast(s.arguments(0), StringType), inputs, binding), - exprToProtoInternal(s.arguments(1), inputs, binding)) - - if (argsExpr.forall(_.isDefined)) { - scalarFunctionExprToProto("read_side_padding", argsExpr: _*) - } else { - withInfo(expr, s.arguments: _*) - None - } - - case s: StaticInvoke - if s.staticObject == classOf[BitmapExpressionUtils] && - s.dataType.isInstanceOf[BinaryType] && - s.functionName == "bitmapCount" && - s.arguments.size == 1 => - val childProto = exprToProto(s.arguments.head, inputs, binding) - val bitmapCountScalarExpr = - scalarFunctionExprToProtoWithReturnType("bitmap_count", IntegerType, childProto) - optExprWithInfo(bitmapCountScalarExpr, expr, expr.children: _*) - case KnownFloatingPointNormalized(NormalizeNaNAndZero(expr)) => val dataType = serializeDataType(expr.dataType) if (dataType.isEmpty) { diff --git a/spark/src/main/scala/org/apache/comet/serde/statics.scala b/spark/src/main/scala/org/apache/comet/serde/statics.scala new file mode 100644 index 0000000000..5093a4f338 --- /dev/null +++ b/spark/src/main/scala/org/apache/comet/serde/statics.scala @@ -0,0 +1,51 @@ +/* + * 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.comet.serde + +import org.apache.spark.sql.catalyst.expressions.{Attribute, BitmapExpressionUtils, Expression} +import org.apache.spark.sql.catalyst.expressions.objects.StaticInvoke +import org.apache.spark.sql.catalyst.util.CharVarcharCodegenUtils + +import org.apache.comet.CometSparkSessionExtensions.withInfo + +object CometStaticInvoke extends CometExpressionSerde[StaticInvoke] { + + private val staticInvokeExpressions: Map[(Class[_], String), CometScalarFunction[_]] = + Map( + (classOf[BitmapExpressionUtils], "bitmapCount") -> CometScalarFunction("bitmap_count"), + (classOf[CharVarcharCodegenUtils], "read_side_padding") -> CometScalarFunction( + "read_side_padding")) + + override def convert( + expr: StaticInvoke, + inputs: Seq[Attribute], + binding: Boolean): Option[ExprOuterClass.Expr] = { + staticInvokeExpressions.get((expr.staticObject, expr.functionName)) match { + case Some(handler) => + handler.convert(expr.asInstanceOf[Expression], inputs, binding) + case None => + withInfo( + expr, + s"Static invoke expression: ${expr.functionName} is not supported", + expr.children: _*) + None + } + } +} diff --git a/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala b/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala index b78a3c863b..17108a27ea 100644 --- a/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala +++ b/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala @@ -52,8 +52,21 @@ class CometBitmapExpressionSuite extends CometTestBase with AdaptiveSparkPlanHel val table = spark.read.parquet(filename) table.createOrReplaceTempView("t1") val df = sql("SELECT bitmap_count(c13) FROM t1") - df.explain(true) checkSparkAnswerAndOperator(df) } } + + test("readSidePadding") { + // https://stackoverflow.com/a/46290728 + val table = "test" + withTable(table) { + sql(s"create table $table(col1 CHAR(2)) using parquet") + sql(s"insert into $table values('é')") // unicode 'e\\u{301}' + sql(s"insert into $table values('é')") // unicode '\\u{e9}' + sql(s"insert into $table values('')") + sql(s"insert into $table values('ab')") + + checkSparkAnswerAndOperator(s"SELECT * FROM $table") + } + } } From 05cb8718b14e2bd7429b8f1d3144f24f1e64020a Mon Sep 17 00:00:00 2001 From: Kazantsev Maksim Date: Sat, 4 Oct 2025 20:08:22 +0400 Subject: [PATCH 3/6] Complete bitmap_count func impl --- .../org/apache/comet/serde/bitmaps.scala | 37 ------------------- .../org/apache/comet/serde/statics.scala | 9 +++-- .../comet/CometBitmapExpressionSuite.scala | 14 ------- 3 files changed, 5 insertions(+), 55 deletions(-) delete mode 100644 spark/src/main/scala/org/apache/comet/serde/bitmaps.scala diff --git a/spark/src/main/scala/org/apache/comet/serde/bitmaps.scala b/spark/src/main/scala/org/apache/comet/serde/bitmaps.scala deleted file mode 100644 index 1468e600d3..0000000000 --- a/spark/src/main/scala/org/apache/comet/serde/bitmaps.scala +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.comet.serde - -import org.apache.spark.sql.catalyst.expressions.{Attribute, BitmapCount} -import org.apache.spark.sql.types.IntegerType - -import org.apache.comet.serde.QueryPlanSerde.{exprToProto, optExprWithInfo, scalarFunctionExprToProtoWithReturnType} - -object CometBitmapCount extends CometExpressionSerde[BitmapCount] { - override def convert( - expr: BitmapCount, - inputs: Seq[Attribute], - binding: Boolean): Option[ExprOuterClass.Expr] = { - val childProto = exprToProto(expr.child, inputs, binding) - val bitmapCountScalarExpr = - scalarFunctionExprToProtoWithReturnType("bitmap_count", IntegerType, childProto) - optExprWithInfo(bitmapCountScalarExpr, expr, expr.children: _*) - } -} diff --git a/spark/src/main/scala/org/apache/comet/serde/statics.scala b/spark/src/main/scala/org/apache/comet/serde/statics.scala index 5093a4f338..b39f3d78eb 100644 --- a/spark/src/main/scala/org/apache/comet/serde/statics.scala +++ b/spark/src/main/scala/org/apache/comet/serde/statics.scala @@ -19,7 +19,7 @@ package org.apache.comet.serde -import org.apache.spark.sql.catalyst.expressions.{Attribute, BitmapExpressionUtils, Expression} +import org.apache.spark.sql.catalyst.expressions.{Attribute, BitmapExpressionUtils} import org.apache.spark.sql.catalyst.expressions.objects.StaticInvoke import org.apache.spark.sql.catalyst.util.CharVarcharCodegenUtils @@ -27,10 +27,11 @@ import org.apache.comet.CometSparkSessionExtensions.withInfo object CometStaticInvoke extends CometExpressionSerde[StaticInvoke] { - private val staticInvokeExpressions: Map[(Class[_], String), CometScalarFunction[_]] = + private val staticInvokeExpressions + : Map[(Class[_], String), CometExpressionSerde[StaticInvoke]] = Map( (classOf[BitmapExpressionUtils], "bitmapCount") -> CometScalarFunction("bitmap_count"), - (classOf[CharVarcharCodegenUtils], "read_side_padding") -> CometScalarFunction( + (classOf[CharVarcharCodegenUtils], "readSidePadding") -> CometScalarFunction( "read_side_padding")) override def convert( @@ -39,7 +40,7 @@ object CometStaticInvoke extends CometExpressionSerde[StaticInvoke] { binding: Boolean): Option[ExprOuterClass.Expr] = { staticInvokeExpressions.get((expr.staticObject, expr.functionName)) match { case Some(handler) => - handler.convert(expr.asInstanceOf[Expression], inputs, binding) + handler.convert(expr, inputs, binding) case None => withInfo( expr, diff --git a/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala b/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala index 17108a27ea..d0362a0e6c 100644 --- a/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala +++ b/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala @@ -55,18 +55,4 @@ class CometBitmapExpressionSuite extends CometTestBase with AdaptiveSparkPlanHel checkSparkAnswerAndOperator(df) } } - - test("readSidePadding") { - // https://stackoverflow.com/a/46290728 - val table = "test" - withTable(table) { - sql(s"create table $table(col1 CHAR(2)) using parquet") - sql(s"insert into $table values('é')") // unicode 'e\\u{301}' - sql(s"insert into $table values('é')") // unicode '\\u{e9}' - sql(s"insert into $table values('')") - sql(s"insert into $table values('ab')") - - checkSparkAnswerAndOperator(s"SELECT * FROM $table") - } - } } From a76a14698c41944644c43e277ba016d2f66befc7 Mon Sep 17 00:00:00 2001 From: Kazantsev Maksim Date: Sat, 4 Oct 2025 20:31:04 +0400 Subject: [PATCH 4/6] Fix --- .../scala/org/apache/comet/CometBitmapExpressionSuite.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala b/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala index d0362a0e6c..044c4a563a 100644 --- a/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala +++ b/spark/src/test/scala/org/apache/comet/CometBitmapExpressionSuite.scala @@ -23,12 +23,11 @@ import scala.util.Random import org.apache.hadoop.fs.Path import org.apache.spark.sql.CometTestBase -import org.apache.spark.sql.execution.adaptive.AdaptiveSparkPlanHelper import org.apache.comet.CometSparkSessionExtensions.isSpark35Plus import org.apache.comet.testing.{DataGenOptions, ParquetGenerator} -class CometBitmapExpressionSuite extends CometTestBase with AdaptiveSparkPlanHelper { +class CometBitmapExpressionSuite extends CometTestBase { test("bitmap_count") { assume(isSpark35Plus) From 0e3ce807d128ea6c2ecf9fc04b043ef3de676dab Mon Sep 17 00:00:00 2001 From: Kazantsev Maksim Date: Tue, 7 Oct 2025 12:28:35 +0400 Subject: [PATCH 5/6] Fix CI pipeline --- .github/workflows/pr_build_linux.yml | 1 + .github/workflows/pr_build_macos.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/pr_build_linux.yml b/.github/workflows/pr_build_linux.yml index 9b918ad8b2..5817eeac55 100644 --- a/.github/workflows/pr_build_linux.yml +++ b/.github/workflows/pr_build_linux.yml @@ -149,6 +149,7 @@ jobs: org.apache.comet.CometBitwiseExpressionSuite org.apache.comet.CometMapExpressionSuite org.apache.comet.objectstore.NativeConfigSuite + org.apache.comet.CometBitmapExpressionSuite - name: "sql" value: | org.apache.spark.sql.CometToPrettyStringSuite diff --git a/.github/workflows/pr_build_macos.yml b/.github/workflows/pr_build_macos.yml index fb6a8295bc..bb996e17e0 100644 --- a/.github/workflows/pr_build_macos.yml +++ b/.github/workflows/pr_build_macos.yml @@ -114,6 +114,7 @@ jobs: org.apache.comet.CometBitwiseExpressionSuite org.apache.comet.CometMapExpressionSuite org.apache.comet.objectstore.NativeConfigSuite + org.apache.comet.CometBitmapExpressionSuite - name: "sql" value: | org.apache.spark.sql.CometToPrettyStringSuite From 728b7c9338b6e333e2f2dc47485d5b5f88511043 Mon Sep 17 00:00:00 2001 From: Kazantsev Maksim Date: Tue, 7 Oct 2025 21:08:12 +0400 Subject: [PATCH 6/6] Fix --- .../main/scala/org/apache/comet/serde/statics.scala | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/spark/src/main/scala/org/apache/comet/serde/statics.scala b/spark/src/main/scala/org/apache/comet/serde/statics.scala index b39f3d78eb..00f8bb2957 100644 --- a/spark/src/main/scala/org/apache/comet/serde/statics.scala +++ b/spark/src/main/scala/org/apache/comet/serde/statics.scala @@ -19,26 +19,23 @@ package org.apache.comet.serde -import org.apache.spark.sql.catalyst.expressions.{Attribute, BitmapExpressionUtils} +import org.apache.spark.sql.catalyst.expressions.Attribute import org.apache.spark.sql.catalyst.expressions.objects.StaticInvoke -import org.apache.spark.sql.catalyst.util.CharVarcharCodegenUtils import org.apache.comet.CometSparkSessionExtensions.withInfo object CometStaticInvoke extends CometExpressionSerde[StaticInvoke] { - private val staticInvokeExpressions - : Map[(Class[_], String), CometExpressionSerde[StaticInvoke]] = + private val staticInvokeExpressions: Map[String, CometExpressionSerde[StaticInvoke]] = Map( - (classOf[BitmapExpressionUtils], "bitmapCount") -> CometScalarFunction("bitmap_count"), - (classOf[CharVarcharCodegenUtils], "readSidePadding") -> CometScalarFunction( - "read_side_padding")) + "bitmapCount" -> CometScalarFunction("bitmap_count"), + "readSidePadding" -> CometScalarFunction("read_side_padding")) override def convert( expr: StaticInvoke, inputs: Seq[Attribute], binding: Boolean): Option[ExprOuterClass.Expr] = { - staticInvokeExpressions.get((expr.staticObject, expr.functionName)) match { + staticInvokeExpressions.get(expr.functionName) match { case Some(handler) => handler.convert(expr, inputs, binding) case None =>