Repository: parquet-go/parquet-go (go)

Issue:
`SortingWriter` do not apply `SkipPageBounds` option
`SkipPageBounds` added in #145. It works well for `GenericWriter[T]` but not working for `SortingWriter[T]` - it still produce min-max values in indexes.


Pull request description:
Fix #293 (apply SkipPageBounds to SortingWriter[T])
`SortingWriter[T]` produce `min` / `max` index value even if `SkipPageBounds` option provided. `SkipPageBounds` added in #145.

(#294 was closed by mistake).

Patch:
diff --git a/config.go b/config.go
index 001e08f..fb1e9d9 100644
--- a/config.go
+++ b/config.go
@@ -297,6 +297,7 @@ func (c *WriterConfig) ConfigureWriter(config *WriterConfig) {
 		BloomFilters:         coalesceBloomFilters(c.BloomFilters, config.BloomFilters),
 		Compression:          coalesceCompression(c.Compression, config.Compression),
 		Sorting:              coalesceSortingConfig(c.Sorting, config.Sorting),
+		SkipPageBounds:       coalesceSkipPageBounds(c.SkipPageBounds, config.SkipPageBounds),
 		Encodings:            encodings,
 	}
 }
@@ -845,6 +846,13 @@ func coalesceBloomFilters(f1, f2 []BloomFilterColumn) []BloomFilterColumn {
 	return f2
 }
 
+func coalesceSkipPageBounds(b1, b2 [][]string) [][]string {
+	if b1 != nil {
+		return b1
+	}
+	return b2
+}
+
 func coalesceCompression(c1, c2 compress.Codec) compress.Codec {
 	if c1 != nil {
 		return c1


Test patch:
diff --git a/sorting_test.go b/sorting_test.go
index 796346d..7486706 100644
--- a/sorting_test.go
+++ b/sorting_test.go
@@ -8,6 +8,7 @@ import (
 	"os"
 	"reflect"
 	"slices"
+	"strconv"
 	"testing"
 	"time"
 
@@ -379,3 +380,62 @@ func TestMergedRowsCorruptedString(t *testing.T) {
 		}
 	}
 }
+
+func TestIssue293(t *testing.T) {
+	type Row struct {
+		Value1 string `parquet:"value1"`
+		Value2 string `parquet:"value2"`
+		Value3 string `parquet:"value3"`
+	}
+
+	rows := make([]Row, 10)
+	for i := range rows {
+		rows[i].Value1 = strconv.Itoa(-i)
+		rows[i].Value2 = strconv.Itoa(i)
+		rows[i].Value3 = strconv.Itoa(i * i)
+	}
+
+	buffer := bytes.NewBuffer(nil)
+	writer := parquet.NewSortingWriter[Row](buffer, 9,
+		parquet.SkipPageBounds("value1"),
+		parquet.SkipPageBounds("value3"),
+		parquet.SortingWriterConfig(
+			parquet.SortingColumns(
+				parquet.Ascending("value1"),
+				parquet.Descending("value2"),
+			),
+		),
+	)
+
+	if _, err := writer.Write(rows); err != nil {
+		t.Fatal(err)
+	}
+
+	if err := writer.Close(); err != nil {
+		t.Fatal(err)
+	}
+
+	f, err := parquet.OpenFile(bytes.NewReader(buffer.Bytes()), int64(buffer.Len()))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	bounds := [][2]string{
+		{"", ""},
+		{"0", "9"},
+		{"", ""},
+	}
+	for i := range 3 {
+		stats := f.Metadata().RowGroups[0].Columns[i].MetaData.Statistics
+
+		min := string(stats.MinValue)
+		if bounds[i][0] != min {
+			t.Fatalf("wrong `min` value in column %d, expected %q, actual %q", i, bounds[i][0], min)
+		}
+
+		max := string(stats.MaxValue)
+		if bounds[i][1] != max {
+			t.Fatalf("wrong `max` value in column %d, expected %q, actual %q", i, bounds[i][1], max)
+		}
+	}
+}