ForVic commented on code in PR #59486:
URL: https://github.com/apache/spark/pull/59486#discussion_r4406404238


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/parquet/ParquetStorageFilter.scala:
##########
@@ -142,17 +144,26 @@ object ParquetStorageFilter {
       maxSplicedRowGroupBytes: Long): ParquetStorageFilter = {
     require(boundExpressions.nonEmpty,
       "storage filters must be non-empty; callers with nothing to push must 
not call create")
-    val expr = boundExpressions.reduce(And)
+    // The conjuncts over the blooms' key columns go under an `If` on the 
blooms, so they run only
+    // on the rows the blooms keep. In one `And`, subexpression elimination 
would compute what
+    // they share on every row.
+    val (blooms, onKeys) = 
boundExpressions.partition(_.isInstanceOf[BloomFilterMightContain])

Review Comment:
   `create` now puts `IsNotNull` first among the key conditions, as 
`FilterExec` does. I added `an IsNotNull over the key columns is evaluated 
before the other conjuncts over them`, which uses your probe 
(`assert_not_null(k) > 0 AND isnotnull(k)` with odd keys null). It asserts the 
same rows as a plain read, 999 excluded, and no row group given up. It fails 
without the reordering.
   



##########
sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/FileSourceStrategy.scala:
##########
@@ -345,20 +359,23 @@ object FileSourceStrategy extends Strategy with 
PredicateHelper with Logging {
       // Offered conjuncts become `storageFilters` on the scan and stay in the 
post-scan Filter too.
       // This runs here because eligibility depends on the data columns the 
reader reads.
       val readerDataColumns = readDataColumns ++ generatedMetadataColumns
-      val storageFilters = storageFiltersFor(
-        normalizedFilters, fsRelation, readDataColumns, 
readerDataColumns.toStructType)
       // The column the reader marks the rows it checked in, see
       // `FileFormat.buildReaderWithStorageFilters`. It is added only where 
the scan still returns
       // columnar batches with it, as `FileSourceScanExec.supportsColumnar` 
decides, so the column
       // never changes how the scan runs. Above a row-based scan, the Project 
that drops the
       // column would copy every surviving row.
-      val storageFilterCheckedColumn = Option.when(storageFilters.nonEmpty) {
+      val checkedColumn =
         AttributeReference(FileFormat.STORAGE_FILTER_CHECKED_COLUMN_NAME, 
BooleanType)()
-      }.filter { checked =>
+      val marksChecked = {

Review Comment:
   Fixed. After the rebase onto SPARK-60465, `storageFiltersFor` returns the 
offered conjuncts together with the checked column from 
`StorageFilterPlanning.checkedColumn`. That builds nothing when no bloom is 
offered, so a scan without storage filters no longer creates the attribute or 
walks its fields. The post-scan Filter passes 
`storageFilters.filterNot(_.isInstanceOf[IsNotNull])` to `skipCheckedRows`, so 
the shared helper is unchanged.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to