An owning, Arrow-LargeUtf8-compatible variable-length string column.
Storage is Arrow-like and contiguous: offsets (int64, 1-based Fortran array with
offsets(1)=0, logical length nrows+1), a packed data byte payload, and a lazily
allocated bit-packed validity bitmap (1=valid). Element i (1-based) occupies
data(offsets(i)+1 : offsets(i+1)). All components are private; access is via the
type-bound procedures. Row/character indexing is integer(int64) throughout.
Reset to empty and release all owned buffers.
Binding form of parquet_string_column_clear; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
Grow capacity for at least n_rows/n_characters.
Binding form of parquet_string_column_reserve_i32; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | n_rows |
required row capacity. |
||
| integer(kind=int32), | intent(in) | :: | n_characters |
required character capacity (bytes). |
Binding form of parquet_string_column_reserve_i64; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | n_rows |
required row capacity. |
||
| integer(kind=int64), | intent(in) | :: | n_characters |
required character capacity (bytes). |
Reallocate buffers down to the current size.
Binding form of parquet_string_column_shrink_to_fit; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
Current row capacity.
Binding form of parquet_string_column_capacity; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
Current character-buffer capacity (bytes).
Binding form of parquet_string_column_character_capacity; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
Number of elements stored.
Binding form of parquet_string_column_size; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
Total characters stored.
Binding form of parquet_string_column_character_size; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
.true. when no rows are stored.
Returns .true. when the column holds no rows.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
Number of null elements.
Binding form of parquet_string_column_null_count; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
Whether the validity bitmap exists yet.
Binding form of parquet_string_column_has_validity; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
Materialize the validity bitmap up front.
Binding form of parquet_string_column_reserve_validity; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
Total bytes of allocated buffers.
Returns the total bytes of allocated buffers (offsets + data + validity + object overhead).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
Verify class invariants.
Verifies all class invariants and internal consistency; returns .true. when they hold.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| character(len=:), | intent(out), | optional, | allocatable | :: | message |
diagnostic on failure. |
Length of element i (no allocation).
int32 specific of length; see the length generic.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
||
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
int64 specific of length: length of element i without allocating. A null element returns 0
by default, or error stops when check_null is .true.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
||
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
Writes element i into an allocatable string.
Binding form of parquet_string_column_get_i32; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
||
| character(len=:), | intent(out), | allocatable | :: | res |
element i (unallocated if null and allowed). |
|
| character(len=*), | intent(in), | optional | :: | null_value |
substitute returned for a null element. |
|
| logical, | intent(in), | optional | :: | allow_null |
.true. => suppress abort, return empty string for a null. |
Binding form of parquet_string_column_get_i64; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
||
| character(len=:), | intent(out), | allocatable | :: | res |
element i (unallocated if null and allowed). |
|
| character(len=*), | intent(in), | optional | :: | null_value |
substitute returned for a null element. |
|
| logical, | intent(in), | optional | :: | allow_null |
.true. => suppress abort, return empty string for a null. |
Copies element i into a fixed-length slot.
Binding form of parquet_string_column_copy_to_i32; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(out) | :: | dest |
receives the element, blank-padded. |
||
| logical, | intent(in), | optional | :: | allow_null |
.true. => a null yields blanks. |
Binding form of parquet_string_column_copy_to_i64; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(out) | :: | dest |
receives the element, blank-padded. |
||
| logical, | intent(in), | optional | :: | allow_null |
.true. => a null yields blanks. |
Zero-copy handle to element i.
int32 specific of view; see the view generic.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in), | target | :: | self |
the column (must be a target). |
|
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
handle to element i.
int64 specific of view: a zero-copy handle to element i. The column must be declared with
the target attribute and must outlive the handle.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in), | target | :: | self |
the column (must be a target). |
|
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
handle to element i.
One handle per element, in order.
Fills data_string with one handle per element of self, in order (view(1), view(2), ...). Aborts if size(data_string) does not match self%size() (rather than silently clipping to the shorter length, which would hide a caller bug behind a partially-populated result).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in), | target | :: | self |
the column (must be a target). |
|
| type(parquet_string), | intent(out), | dimension(:) | :: | data_string |
receives one handle per element. |
One handle per row of [first, last].
int32 specific of view_slice; see the view_slice generic.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in), | target | :: | self |
the column (must be a target). |
|
| integer(kind=int32), | intent(in) | :: | first |
first row of the range (1-based, inclusive). |
||
| integer(kind=int32), | intent(in) | :: | last |
last row of the range (1-based, inclusive). |
||
| type(parquet_string), | intent(out), | dimension(:) | :: | data_string |
one handle per row in [first, last]. |
int64 specific of view_slice: fills data_string with one zero-copy handle per row of [first, last] (1-based, inclusive), in order (data_string(1) = view(first), ...) -- view_all restricted to a range. Aborts if size(data_string) /= last-first+1, same convention as view_all.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in), | target | :: | self |
the column (must be a target). |
|
| integer(kind=int64), | intent(in) | :: | first |
first row of the range (1-based, inclusive). |
||
| integer(kind=int64), | intent(in) | :: | last |
last row of the range (1-based, inclusive). |
||
| type(parquet_string), | intent(out), | dimension(:) | :: | data_string |
one handle per row in [first, last]. |
Whether element i is null.
Binding form of parquet_string_column_is_null_i32; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
Binding form of parquet_string_column_is_null_i64; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
Whether element i has zero length.
int32 specific of is_empty; see the is_empty generic.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
||
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
int64 specific of is_empty: whether element i has zero length. A null element returns
.true. by default, or error stops when check_null is .true.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
||
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
Append a string to the end.
Appends a string to the end of the column. By default the string is stored verbatim; pass
strip=.true. to remove leading and trailing blanks, or trim=.true. to remove trailing
blanks only (trim is ignored when strip is .true.). Automatically grows capacity.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| character(len=*), | intent(in) | :: | str |
the string to append. |
||
| logical, | intent(in), | optional | :: | strip |
remove leading and trailing blanks. |
|
| logical, | intent(in), | optional | :: | trim |
remove trailing blanks only. |
Append a null element to the end.
Binding form of parquet_string_column_append_null; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
Append all elements from another column.
Binding form of parquet_string_column_append_column; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the destination column. |
||
| type(parquet_string_column), | intent(in) | :: | other |
the source column. |
Bulk-append a character array, trimming each element.
Binding form of parquet_string_column_append_values; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column, appended to. |
||
| character(len=*), | intent(in), | contiguous | :: | values(:) |
elements to append; blanks trimmed. |
|
| logical, | intent(in), | optional | :: | is_null(:) |
.true. => append that element as null. |
Append one element of another column.
Binding form of parquet_string_column_append_from_i32; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the destination column. |
||
| type(parquet_string_column), | intent(in) | :: | src |
the source column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based source element index. |
Binding form of parquet_string_column_append_from_i64; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the destination column. |
||
| type(parquet_string_column), | intent(in) | :: | src |
the source column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based source element index. |
Clears self, then fills it -- from an array of handles, or from a character array (trailing blanks trimmed, one optional null mask). Both replace the whole column.
Clears self, then gathers an array of independently-obtained parquet_string handles into it (each handle's referenced element becomes one row, in array order; a null handle becomes %append_null()). Every handle is validated before self is cleared or otherwise touched: aborts if any handle aliases self (self%clear() would corrupt it before it could be read), is unassociated, or refers to a stale/out-of-range index. The first handle (in array order) that trips any of these three checks (in that priority order) determines the abort message -- other handles are not scanned once one is found.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout), | target | :: | self |
cleared, then filled from handles. |
|
| type(parquet_string), | intent(in) | :: | handles(:) |
source handles, in order. |
Character-array specific of build_from: clears the column and rebuilds it from values,
trimming each element's trailing blanks.
Why this exists rather than a loop of %append_string. Every element of a
character(len=*) array shares one declared length, so filling a column this way is the
single commonest thing anyone does with one -- and doing it per element costs a call that
re-derives the trim, re-checks two capacities that are already known to be sufficient, and
copies the payload with transfer(str(lo:hi), self%data, slen), which builds a temporary per
element because the payload is character(len=1), allocatable. Measured on 1M x
character(len=24): 55.5 ms of per-element calls against 9.5 ms here, taking
parquet_column%set_all from 65.2 ms to 9.5 ms overall (feature_optimise_A7.md, S7-5).
The trick that removes the per-element transfer, and the reason for the contiguous
attribute. values is a contiguous array of character(len=w), so its bytes are one
w*n block; pack_character_bytes below re-sees exactly that block through a
character(len=1) :: src(*) dummy by sequence association, after which each element's
payload copy is an ordinary section-to-section assignment between two character(len=1)
arrays -- the same shape build_from_handles' phase 3 uses, and no temporary. Sequence
association needs the actual argument to be contiguous, which is what contiguous here
guarantees (at the cost of a copy-in for the rare strided caller).
len_trim stays on the ELEMENT view and must not be hand-rolled. Replacing it with a
trailing-blank scan over the byte view -- which looks like the natural thing to do once the
byte view exists -- measured 3x slower (32.5 ms against 9.5): the intrinsic is far better
than a per-byte loop. len_trim is then the floor here, at ~7.5 ns/element.
is_null, when present, marks those elements null: they occupy a zero-width slot, exactly
as %append_null would leave them, and their values entry is ignored.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
cleared, then filled from |
||
| character(len=*), | intent(in), | contiguous | :: | values(:) |
source elements; trailing blanks trimmed. |
|
| logical, | intent(in), | optional | :: | is_null(:) |
.true. => store that element as null. |
Replace the content of element i.
Binding form of parquet_string_column_set_i32; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(in) | :: | str |
the replacement string. |
||
| logical, | intent(in), | optional | :: | strip |
remove leading and trailing blanks. |
|
| logical, | intent(in), | optional | :: | trim |
remove trailing blanks only. |
Binding form of parquet_string_column_set_i64; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(in) | :: | str |
the replacement string. |
||
| logical, | intent(in), | optional | :: | strip |
remove leading and trailing blanks. |
|
| logical, | intent(in), | optional | :: | trim |
remove trailing blanks only. |
Sets element i to null (discards any content).
Binding form of parquet_string_column_set_null_i32; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
Binding form of parquet_string_column_set_null_i64; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
Remove element i (shifts later elements down).
int32 specific of erase; see the erase generic.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
int64 specific of erase: removes element i, shifting all later elements down by one (immediate compaction, order-preserving, O(N)). Invalidates handles at index >= i.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
Reorder every element by a permutation.
Binding form of parquet_string_column_reindex_i32; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | perm(:) |
1-based permutation of 1..size(). |
Binding form of parquet_string_column_reindex_i64; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | perm(:) |
1-based permutation of 1..size(). |
INTERNAL -- reindex without the duplicate/range scan. Public only because Fortran offers no narrower visibility -- see reindex_trusted_i64.
Binding form of parquet_string_column_reindex_trusted_i32; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | perm(:) |
1-based permutation of 1..size(). |
Binding form of parquet_string_column_reindex_trusted_i64; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | perm(:) |
1-based permutation of 1..size(). |
Keep only the elements whose mask entry is .true.
Binding form of parquet_string_column_delete_by_mask; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| logical, | intent(in) | :: | keep(:) |
.true. for every element to retain. |
Keep the listed elements, in the listed order.
Binding form of parquet_string_column_gather_i32; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | idx(:) |
1-based source index per destination element. |
Binding form of parquet_string_column_gather_i64; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | idx(:) |
1-based source index per destination element. |
Append n null elements in bulk.
Binding form of parquet_string_column_append_nulls_i32; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | n |
number of null elements to append. |
Binding form of parquet_string_column_append_nulls_i64; forwards to it,
keeping the implementation at the type end (feature_ifx.md).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | n |
number of null elements to append. |
Strip both ends of every non-null element.
Strips leading and trailing blanks from every non-null element, in place (O(nchars)).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
Trailing-trim every non-null element.
Trailing-trims every non-null element, in place (O(nchars)).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the column. |
Index of first/last element equal to str.
Returns the 1-based index of the first element equal to str, or 0 if none. By default
the comparison is byte-exact; pass exact=.false. to trailing-trim both sides. Pass
reverse=.true. to scan from the last row backward (returning the last match). Null
elements never match.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| character(len=*), | intent(in) | :: | str |
the query string. |
||
| logical, | intent(in), | optional | :: | exact |
.false. => trailing-trim both sides. |
|
| logical, | intent(in), | optional | :: | reverse |
.true. => search from the back. |
Whether element i contains a substring.
int32 specific of contains; see the contains generic.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(in) | :: | str |
substring to search for. |
||
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
int64 specific of contains: whether element i contains str as a substring (exact bytes,
empty substring matches). A null element returns .false. by default, or error stops when
check_null is .true.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(in) | :: | str |
substring to search for. |
||
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
Whether element i begins with prefix.
int32 specific of startswith; see the startswith generic.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(in) | :: | prefix |
prefix to test. |
||
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
int64 specific of startswith: whether element i begins with prefix (exact bytes, empty
prefix matches). A null element returns .false. by default, or error stops when
check_null is .true.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(in) | :: | prefix |
prefix to test. |
||
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
Whether element i ends with suffix.
int32 specific of endswith; see the endswith generic.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(in) | :: | suffix |
suffix to test. |
||
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
int64 specific of endswith: whether element i ends with suffix (exact bytes, empty suffix
matches). A null element returns .false. by default, or error stops when check_null is .true.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(in) | :: | suffix |
suffix to test. |
||
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
Whether element i equals str.
int32 specific of equals; see the equals generic.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int32), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(in) | :: | str |
query string. |
||
| logical, | intent(in), | optional | :: | exact |
.false. => trailing-trim both sides. |
|
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
int64 specific of equals: whether element i equals str. By default the comparison is
byte-exact; pass exact=.false. to trailing-trim both sides. A null element returns .false.
by default, or error stops when check_null is .true.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based element index. |
||
| character(len=*), | intent(in) | :: | str |
query string. |
||
| logical, | intent(in), | optional | :: | exact |
.false. => trailing-trim both sides. |
|
| logical, | intent(in), | optional | :: | check_null |
.true. => error stop on a null element. |
Orders element i against element j.
Orders element i against element j: -1 when i sorts first, +1 when j does, 0 when equal.
Exactly Fortran's own < on the two values, blanks and all: the shorter element is
compared as though padded with blanks, so "ab" and "ab " are equal and "ab" sorts before
"abc". That is deliberate rather than incidental — it means a caller can replace
call c%get(i, a); call c%get(j, b); if (a < b) ... with this and get the same answer.
Why this exists: so that a min/max scan need not materialize every element. Finding the
smallest and largest value by fetching each one through %get costs a heap allocation per row
— roughly 0.11 s per 4 M elements — where tracking the two winning indices through this and
fetching only those two at the end costs none. See feature_risks.md Risk-60.
Null elements are not special-cased. A null is zero-width, so it compares as an empty
string and sorts first; a caller that needs nulls ordered differently must test %is_null
itself, exactly as it would around %get.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(in) | :: | i |
1-based index of the first element. |
||
| integer(kind=int64), | intent(in) | :: | j |
1-based index of the second element. |
Materialize the whole column as a char array.
Materializes the whole column into a conventional Fortran character array out, each
element blank-padded to the longest element's length. A null element error stops by default;
pass null_value to substitute a string for nulls.
The payload is copied straight out of data, never through %get. %get allocates a
deferred-length temporary per element, and a whole-column loop over it costs one heap
allocation, one fill, one copy into out(i) and one free per row -- which measured as
71 % of this procedure, not the copying it was there to do. Do not reintroduce a
character(len=:), allocatable intermediate here, or in any other bulk operation over this
type; see feature_risks.md Risk-60.
The fill loop threads with no restructure, unlike reindex_apply: out(i) is maxlen
bytes at a fixed stride, so every element's destination is known from i alone and there is
no write cursor to carry. There is no serial twin here for that reason -- with nt == 1 this
is the original loop, so nothing is slower for a caller that does not thread.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| character(len=:), | intent(out), | allocatable | :: | out(:) |
materialized, padded strings. |
|
| character(len=*), | intent(in), | optional | :: | null_value |
substitute for null elements. |
Independent deep copy.
Returns an independent deep copy of the column (shrunk to the current size). Mutating either object never affects the other.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the source column. |
the deep copy.
Independent, owning copy of rows [first, last].
int32 specific of slice; see the slice generic.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the source column. |
||
| integer(kind=int32), | intent(in) | :: | first |
first row of the range (1-based, inclusive). |
||
| integer(kind=int32), | intent(in) | :: | last |
last row of the range (1-based, inclusive). |
||
| type(parquet_string_column), | intent(inout) | :: | dest |
cleared, then filled with rows [first, last]. |
int64 specific of slice: materializes an independent, owning copy of rows [first, last] (1-based, inclusive) into dest -- one bulk data memcpy, one vectorized offset-rebase loop, and one validity-bitmap slice, same overall shape as append_column but scoped to the range. dest is cleared first; self is left unchanged.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the source column. |
||
| integer(kind=int64), | intent(in) | :: | first |
first row of the range (1-based, inclusive). |
||
| integer(kind=int64), | intent(in) | :: | last |
last row of the range (1-based, inclusive). |
||
| type(parquet_string_column), | intent(inout) | :: | dest |
cleared, then filled with rows [first, last]. |
Transfer all buffers from another column.
Transfers all buffers from other into self, leaving other a valid empty column. Self's
previous contents are released. Self-move (move_from with the same object) is a no-op.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the destination column. |
||
| type(parquet_string_column), | intent(inout) | :: | other |
the source column (left empty). |
Exchange contents with another column.
Exchanges the contents of self and other in O(1). Symmetric: a%swap(b) == b%swap(a).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the first column. |
||
| type(parquet_string_column), | intent(inout) | :: | other |
the second column. |
Human-readable representation.
Writes a human-readable representation of the column to unit (default: standard output),
showing each element (or max_rows (default 20).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer, | intent(in), | optional | :: | unit |
output unit (default output_unit). |
|
| integer(kind=int64), | intent(in), | optional | :: | max_rows |
max elements to print (default 20). |
Writes a compact one-line overview string.
Writes a compact one-line overview string (row/char/null counts and capacities) into res.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| character(len=:), | intent(out), | allocatable | :: | res |
the summary string. |
Detailed metrics (optional out-args).
Returns detailed metrics via optional intent(out) arguments (kept basic; extensible later).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(out), | optional | :: | nrows |
number of elements. |
|
| integer(kind=int64), | intent(out), | optional | :: | nchars |
total characters. |
|
| integer(kind=int64), | intent(out), | optional | :: | n_null |
number of nulls. |
|
| integer(kind=int64), | intent(out), | optional | :: | min_len |
shortest non-null element length. |
|
| integer(kind=int64), | intent(out), | optional | :: | max_len |
longest non-null element length. |
|
| integer(kind=int64), | intent(out), | optional | :: | row_capacity |
current row capacity. |
|
| integer(kind=int64), | intent(out), | optional | :: | char_capacity |
current character capacity. |
|
| integer(kind=int64), | intent(out), | optional | :: | bytes |
total allocated bytes. |
Export c_loc pointers to the internal buffers.
Exports c_loc pointers to the internal offsets/data/validity buffers plus counts, for the
Parquet writer to consume without materializing strings. The returned pointers are valid
only until the next mutation of the column. validity_ptr is C_NULL_PTR when the column has
no nulls; data_ptr is C_NULL_PTR when the payload is empty.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in), | target | :: | self |
the column (must be a target). |
|
| type(c_ptr), | intent(out) | :: | offsets_ptr |
-> int64 offsets(0:nrows). |
||
| type(c_ptr), | intent(out) | :: | data_ptr |
-> nchars payload bytes. |
||
| type(c_ptr), | intent(out) | :: | validity_ptr |
-> validity bitmap, or C_NULL_PTR. |
||
| integer(kind=int64), | intent(out) | :: | nrows |
number of elements. |
||
| integer(kind=int64), | intent(out) | :: | nchars |
total characters. |
||
| logical, | intent(out) | :: | has_validity |
whether a validity bitmap exists. |
Copy the offsets and packed payload into caller arrays.
Copies this column's offsets and packed payload into caller-provided arrays.
The safe, allocation-free counterpart to raw_buffers: same two buffers, copied rather
than pointed at. Use this when the destination has to own its bytes anyway — raw_buffers
hands back c_loc pointers whose validity depends on the actual argument carrying the
TARGET attribute all the way up the call chain, which is a precondition a caller several
frames away cannot check.
This exists so that bulk consumers never walk the column element by element. Materializing
each element through %get costs one heap allocation, one fill, one copy and one free per row;
at 4 M elements that measured as roughly 0.11 s per allocation, and as 19-33 % of an entire
string sort in the consumer this was added for. The layout handed back is exactly the layout a
packed consumer wants, so the copy is two memcpys rather than a loop.
offsets must hold at least size()+1 entries and data at least character_size() bytes;
both abort otherwise rather than truncating. Only those leading portions are written.
A null element is zero-width here, exactly as it is in the column — set_null compacts the
payload — so a consumer that ignores validity gets an empty string for a null, which is what
%get(..., allow_null=.true.) would have given it.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(in) | :: | self |
the column. |
||
| integer(kind=int64), | intent(out) | :: | offsets(:) |
receives size()+1 offsets; offsets(1) = 0. |
||
| character(len=1), | intent(out) | :: | data(:) |
receives character_size() payload bytes. |
Bulk-append one row group from C buffers.
Bulk-appends one row group straight from C buffers: nrows_in elements with a packed
nchars_in-byte payload, an offsets buffer (int32 when offsets_int32 is .true., else
int64; length nrows_in+1, 0-based), and an optional Arrow validity bitmap (validity =
C_NULL_PTR means all valid). Offsets are rebased onto the existing payload (int32 widened to
int64 in the same pass); the validity bit region is merged (handling a non-byte-aligned join).
Precondition: offsets must already be rebased to this chunk, i.e. its first entry
(offsets(1) in the Fortran 1-based view of the C array) must be exactly 0, and data
must point at the first payload byte that first entry refers to. A source sliced out of
a larger buffer -- e.g. an Arrow array with a non-zero offset() -- is not rebased by
construction and must be rebased by the caller (subtract the slice's own starting offset
from every offsets entry, and advance data by that same amount) before calling this;
passing an un-rebased offsets aborts immediately rather than silently misplacing every
element's bytes. validity, when not C_NULL_PTR, is addressed starting from bit
validity_offset_bits (default 0) rather than assumed to already start at bit 0 -- unlike
offsets/data, Arrow never pre-rebases a validity bitmap for a sliced source array, so a
nonzero source offset() (e.g. a struct-nested leaf resolved through a sliced child array)
must be passed through here explicitly; that misalignment cannot be detected from a raw
bitmap pointer alone; the caller is responsible for reporting the correct offset.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_string_column), | intent(inout) | :: | self |
the destination column. |
||
| integer(kind=int64), | intent(in) | :: | nrows_in |
number of incoming elements. |
||
| integer(kind=int64), | intent(in) | :: | nchars_in |
incoming payload byte count. |
||
| type(c_ptr), | intent(in) | :: | offsets |
-> int32/int64 offsets(0:nrows_in), offsets(0)=0. |
||
| type(c_ptr), | intent(in) | :: | data |
-> nchars_in payload bytes, at offsets(0). |
||
| type(c_ptr), | intent(in) | :: | validity |
-> Arrow bitmap, or C_NULL_PTR. |
||
| logical, | intent(in) | :: | offsets_int32 |
.true. => source offsets are int32. |
||
| integer(kind=int64), | intent(in), | optional | :: | validity_offset_bits |
bit index of element 1 in |
type :: parquet_string_column private integer(int64), allocatable :: offsets(:) !! int64 offsets; offsets(1)=0, length nrows+1. character(len=1), allocatable :: data(:) !! packed byte payload; used bytes = nchars. integer(int8), allocatable :: validity(:) !! bit-packed bitmap (1=valid); lazy. integer(int64) :: nrows = 0 !! number of elements stored. integer(int64) :: nchars = 0 !! total characters stored (= offsets(nrows+1)). integer(int64) :: n_null = 0 !! cached number of null elements. logical :: has_nulls = .false. !! .true. once the validity bitmap is materialized. contains ! --- construction / memory management --- procedure :: clear !! Reset to empty and release all owned buffers. procedure, private :: reserve_i32 !! int32 specific of reserve. procedure, private :: reserve_i64 !! int64 specific of reserve. generic :: reserve => reserve_i32, reserve_i64 !! Grow capacity for at least n_rows/n_characters. procedure :: shrink_to_fit !! Reallocate buffers down to the current size. procedure :: capacity !! Current row capacity. procedure :: character_capacity !! Current character-buffer capacity (bytes). procedure :: size => col_size !! Number of elements stored. procedure :: character_size !! Total characters stored. procedure :: empty => col_empty !! .true. when no rows are stored. procedure :: null_count !! Number of null elements. procedure :: has_validity !! Whether the validity bitmap exists yet. procedure :: reserve_validity !! Materialize the validity bitmap up front. procedure :: memory_usage !! Total bytes of allocated buffers. procedure :: validate !! Verify class invariants. ! --- access --- procedure, private :: length_i32 !! int32 specific of length. procedure, private :: length_i64 !! int64 specific of length. generic :: length => length_i32, length_i64 !! Length of element i (no allocation). procedure, private :: get_i32 !! int32 specific of get. procedure, private :: get_i64 !! int64 specific of get. generic :: get => get_i32, get_i64 !! Writes element i into an allocatable string. procedure, private :: copy_to_i32 !! int32 specific of copy_to. procedure, private :: copy_to_i64 !! int64 specific of copy_to. generic :: copy_to => copy_to_i32, copy_to_i64 !! Copies element i into a fixed-length slot. procedure, private :: view_i32 !! int32 specific of view. procedure, private :: view_i64 !! int64 specific of view. generic :: view => view_i32, view_i64 !! Zero-copy handle to element i. procedure :: view_all !! One handle per element, in order. procedure, private :: view_slice_i32 !! int32 specific of view_slice. procedure, private :: view_slice_i64 !! int64 specific of view_slice. generic :: view_slice => view_slice_i32, view_slice_i64 !! One handle per row of [first, last]. procedure, private :: is_null_i32 !! int32 specific of is_null. procedure, private :: is_null_i64 !! int64 specific of is_null. generic :: is_null => is_null_i32, is_null_i64 !! Whether element i is null. procedure, private :: is_empty_i32 !! int32 specific of is_empty. procedure, private :: is_empty_i64 !! int64 specific of is_empty. generic :: is_empty => is_empty_i32, is_empty_i64 !! Whether element i has zero length. ! --- modification --- procedure :: append_string !! Append a string to the end. procedure :: append_null !! Append a null element to the end. procedure :: append_column !! Append all elements from another column. procedure :: append_values !! Bulk-append a character array, trimming each element. procedure, private :: append_from_i32 !! int32 specific of append_from. procedure, private :: append_from_i64 !! int64 specific of append_from. generic :: append_from => append_from_i32, append_from_i64 !! Append one element of another column. procedure, private :: build_from_handles !! handles specific of build_from. procedure, private :: build_from_character !! character-array specific of build_from. generic :: build_from => build_from_handles, build_from_character !! Clears self, then fills it -- from an array of handles, or from a character array !! (trailing blanks trimmed, one optional null mask). Both replace the whole column. procedure, private :: set_i32 !! int32 specific of set. procedure, private :: set_i64 !! int64 specific of set. generic :: set => set_i32, set_i64 !! Replace the content of element i. procedure, private :: set_null_i32 !! int32 specific of set_null. procedure, private :: set_null_i64 !! int64 specific of set_null. generic :: set_null => set_null_i32, set_null_i64 !! Sets element i to null (discards any content). procedure, private :: erase_i32 !! int32 specific of erase. procedure, private :: erase_i64 !! int64 specific of erase. generic :: erase => erase_i32, erase_i64 !! Remove element i (shifts later elements down). procedure, private :: reindex_i32 !! int32 specific of reindex. procedure, private :: reindex_i64 !! int64 specific of reindex. generic :: reindex => reindex_i32, reindex_i64 !! Reorder every element by a permutation. procedure, private :: reindex_trusted_i32 !! int32 specific of reindex_trusted. procedure, private :: reindex_trusted_i64 !! int64 specific of reindex_trusted. !> INTERNAL -- reindex without the duplicate/range scan. Public only because Fortran offers !! no narrower visibility -- see reindex_trusted_i64. generic :: reindex_trusted => reindex_trusted_i32, reindex_trusted_i64 procedure :: delete_by_mask !! Keep only the elements whose mask entry is .true. procedure, private :: gather_i32 !! int32 specific of gather. procedure, private :: gather_i64 !! int64 specific of gather. generic :: gather => gather_i32, gather_i64 !! Keep the listed elements, in the listed order. procedure, private :: append_nulls_i32 !! int32 specific of append_nulls. procedure, private :: append_nulls_i64 !! int64 specific of append_nulls. generic :: append_nulls => append_nulls_i32, append_nulls_i64 !! Append n null elements in bulk. procedure :: strip_all !! Strip both ends of every non-null element. procedure :: trim_all !! Trailing-trim every non-null element. ! --- searching / comparison --- procedure :: find !! Index of first/last element equal to str. procedure, private :: contains_i32 !! int32 specific of contains. procedure, private :: contains_i64 !! int64 specific of contains. generic :: contains => contains_i32, contains_i64 !! Whether element i contains a substring. procedure, private :: startswith_i32 !! int32 specific of startswith. procedure, private :: startswith_i64 !! int64 specific of startswith. generic :: startswith => startswith_i32, startswith_i64 !! Whether element i begins with prefix. procedure, private :: endswith_i32 !! int32 specific of endswith. procedure, private :: endswith_i64 !! int64 specific of endswith. generic :: endswith => endswith_i32, endswith_i64 !! Whether element i ends with suffix. procedure, private :: equals_i32 !! int32 specific of equals. procedure, private :: equals_i64 !! int64 specific of equals. generic :: equals => equals_i32, equals_i64 !! Whether element i equals str. procedure :: compare !! Orders element i against element j. ! --- conversion / ownership --- procedure :: to_character !! Materialize the whole column as a char array. procedure :: clone !! Independent deep copy. procedure, private :: slice_i32 !! int32 specific of slice. procedure, private :: slice_i64 !! int64 specific of slice. generic :: slice => slice_i32, slice_i64 !! Independent, owning copy of rows [first, last]. procedure :: move_from !! Transfer all buffers from another column. procedure :: swap !! Exchange contents with another column. ! --- diagnostics --- procedure :: print => col_print !! Human-readable representation. procedure :: summary !! Writes a compact one-line overview string. procedure :: statistics !! Detailed metrics (optional out-args). ! --- interop hooks (advanced; for the Parquet read/write integration layer) --- procedure :: raw_buffers !! Export c_loc pointers to the internal buffers. procedure :: copy_buffers !! Copy the offsets and packed payload into caller arrays. procedure :: append_buffers !! Bulk-append one row group from C buffers. ! ! --- NO `final` PROCEDURE, deliberately --- ! ! This type owns three ALLOCATABLE components (offsets, data, validity) and nothing else -- ! no pointer, no handle, no external resource. Fortran deallocates allocatable components ! automatically whenever the object ceases to exist, is deallocated, or is entered as an ! `intent(out)` dummy (F2018 9.7.3.2), so the `final :: finalize_column` this type used to ! carry -- whose entire body was three `if (allocated(x)) deallocate(x)` lines -- freed ! nothing the language was not already freeing. Contrast parquet_writer/parquet_reader/ ! parquet_table, whose finalizers release C++ handles and OpenMP locks the language knows ! nothing about: those are real and must stay. ! ! Do not add one back. Three things now depend on the absence: ! * nagfor 7.2 emits INVALID C under -C=undefined when finalizing an ARRAY whose element ! type has a finalizable COMPONENT. parquet_column embeds one of these, and ! parquet_table_column embeds a parquet_column, so `cache%cols(:)` reached it ! transitively and src/parquet_tables_lifecycle.f90 would not compile. ! * a finalizable type may not go in an OpenMP `private()` clause under gfortran. ! * intrinsic assignment to or from a finalizable type runs the finalizer twice per ! iteration, which a loop assigning columns would pay on every element. end type parquet_string_column