Skip to content

Commit e1ad478

Browse files
committed
Fix for --float-trunc-prec to propagate to nested columns too
1 parent aebda7b commit e1ad478

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

src/blosc2/cli/parquet_to_blosc2.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,8 @@ def import_unnamed_root_separate_cols( # noqa: C901
11011101
"""
11021102

11031103
inner_schema = blosc2.CTable._inner_schema_for_unnamed_root(pa, parquet_schema)
1104+
flat_inner_schema = blosc2.CTable._flatten_arrow_struct_schema(pa, inner_schema)
1105+
float_trunc_column_cparams = build_float_trunc_column_cparams(pa, flat_inner_schema, args)
11041106
total_parquet_rows = pf.metadata.num_rows if pf.metadata is not None else None
11051107

11061108
# ------------------------------------------------------------------
@@ -1187,6 +1189,13 @@ def import_unnamed_root_separate_cols( # noqa: C901
11871189
print(f"Chunks: {args.chunks:,}")
11881190
if args.blocks is not None:
11891191
print(f"Blocks: {args.blocks:,}")
1192+
trunc_global = getattr(args, "float_trunc_prec_global", None)
1193+
trunc_columns = getattr(args, "float_trunc_prec_columns", {})
1194+
if trunc_global is not None:
1195+
print(f"Float trunc precision: {trunc_global} bits (all float columns)")
1196+
if trunc_columns:
1197+
formatted = ", ".join(f"{name}={bits}" for name, bits in sorted(trunc_columns.items()))
1198+
print(f"Float trunc columns: {formatted}")
11901199
print()
11911200

11921201
cparams = blosc2.CParams(codec=blosc2.Codec[args.codec], clevel=args.clevel, use_dict=args.use_dict)
@@ -1204,6 +1213,7 @@ def import_unnamed_root_separate_cols( # noqa: C901
12041213
blosc2_batch_size=args.blosc2_batch_size,
12051214
blosc2_items_per_block=args.blosc2_items_per_block,
12061215
list_serializer=args.list_serializer,
1216+
column_cparams=float_trunc_column_cparams or None,
12071217
create_summary_index=args.create_summary_index,
12081218
chunks=args.chunks,
12091219
blocks=args.blocks,

tests/ctable/test_arrow_interop.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,46 @@ def test_from_arrow_column_cparams(tmp_path):
189189
assert reopened._cols["x"].cparams.filters[:2] == [blosc2.Filter.TRUNC_PREC, blosc2.Filter.SHUFFLE]
190190

191191

192+
def test_from_arrow_column_cparams_nested_struct(tmp_path):
193+
# Regression: column_cparams with TRUNC_PREC must be applied to leaf columns
194+
# produced by struct flattening, not silently dropped.
195+
struct_type = pa.struct(
196+
[
197+
pa.field("lon", pa.float64()),
198+
pa.field("lat", pa.float64()),
199+
]
200+
)
201+
at = pa.table(
202+
{
203+
"pos": pa.array(
204+
[{"lon": -87.6, "lat": 41.8}, {"lon": -87.7, "lat": 41.9}],
205+
type=struct_type,
206+
),
207+
"fare": pa.array([10.0, 20.0], type=pa.float32()),
208+
}
209+
)
210+
trunc_cparams = {
211+
"codec": blosc2.Codec.ZSTD.value,
212+
"clevel": 5,
213+
"typesize": 8,
214+
"filters": [blosc2.Filter.TRUNC_PREC.value, blosc2.Filter.SHUFFLE.value],
215+
"filters_meta": [22, 0],
216+
}
217+
t = CTable.from_arrow(
218+
at.schema,
219+
at.to_batches(),
220+
urlpath=str(tmp_path / "trunc_nested.b2d"),
221+
column_cparams={"pos.lon": trunc_cparams, "pos.lat": trunc_cparams},
222+
)
223+
assert t.col_names == ["pos.lon", "pos.lat", "fare"]
224+
assert t._cols["pos.lon"].cparams.filters[:2] == [blosc2.Filter.TRUNC_PREC, blosc2.Filter.SHUFFLE]
225+
assert t._cols["pos.lon"].cparams.filters_meta[:2] == [22, 0]
226+
assert t._cols["pos.lat"].cparams.filters[:2] == [blosc2.Filter.TRUNC_PREC, blosc2.Filter.SHUFFLE]
227+
# fare is float32, no TRUNC_PREC requested
228+
assert blosc2.Filter.TRUNC_PREC not in t._cols["fare"].cparams.filters
229+
t.close()
230+
231+
192232
def test_from_arrow_string_values():
193233
# Without string_max_length, scalar strings become vlstring columns.
194234
# Accessing [:] on a vlstring column returns a Python list, not an ndarray.

0 commit comments

Comments
 (0)