One row of a table, as a lightweight handle: r = t%row(i).
Non-owning and cheap to make, so it is the natural thing to pass to a procedure that
works on a single row, or to build inside a loop over rows. It resolves the column by
name and the row by index on EVERY access, so it survives anything that merely reallocates
a column's values -- and it triggers the same lazy first touch that %get on the table
does, so a handle can reach a column nothing has read yet.
It points at the table's column STORE, not at the table, which is what lets t%row(i)
return a usable handle without the caller declaring the table target (a pointer to a
dummy's target would be undefined the moment the function returned).
A handle does not survive a structural change, and says so rather than reading the wrong
row: it stamps the table's %generation() when it is made and refuses once they differ.
%is_valid() is the non-aborting way to ask. The rule, the stamp and the message are the
same ones parquet_table_col uses -- two handles with one rule between them.
Still treat it as short-lived: a handle is cheap to make and the refusal is deliberately conservative, so re-fetching inside the loop is the shape to reach for rather than working out which mutations a particular handle could have survived.
No finalizer, deliberately -- and this once had one, row_finalize, which nullified the
pointer, removed on the argument rather than on a measurement. It protected nothing: it ran
at scope exit (the object is already dead), and on r = t%row(i) it nullified a pointer the
copy overwrote a moment later. It could not catch the case that matters either -- a cache
freed with its table leaves associated() answering .true., not .false.. Meanwhile it
cost two finalizer calls per assignment, on the shape this API makes idiomatic, and put the
type in the class CLAUDE.md says never to give to OpenMP's private().
parquet_string still carries the equivalent nullify-only finalizer, so the library is not
uniform here. That is accepted rather than overlooked: it is a released type, its finalizer
has no measured cost, and the consistency that matters is between this handle and
parquet_table_col, which the guide presents as its mirror image.
Copies this row's value for a column into the caller's own variable, widening
int32 -> int64 and float32 -> float64 exactly as the table's own %get does. The
column may be named by a string or by a parquet_table_col handle; the handle
form does no name lookup, which is what a loop over rows would otherwise repeat.
Writes this row's value for a column. The kind must match the column's exactly
(a write never widens), and writing a value CLEARS that row's null. The TABLE is
updated -- a handle is a view of it, not a copy. The column may be named by a
string or by a parquet_table_col handle.
Points p at this row's storage: zero copy, writable, exact kind. A scalar
column gives a scalar pointer, a vector column a pointer to that row's whole
vector. The two string kinds have no %ref -- a packed variable-length store has
no fixed slot to point at -- and the pointer dies with any structural change,
exactly as the table's own %col pointers do.
Whether this row is null in a column, or -- given e -- element e of it.
This row's 1-based index within the table.
This row's 1-based index within its table.
Deliberately pure, and so the one query that does NOT check the stamp: it answers
about the HANDLE ("which row was I made for"), not about the table, and that answer is
still true after a mutation even though reading through the handle is refused. Its
column-handle counterpart %index() does check, because a slot number is about the
table and slots renumber.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_table_row), | intent(in) | :: | self |
the row handle. |
the row index.
Whether the handle is attached AND still current.
Whether the handle is attached to a table AND still current -- one predicate, for the
reason its parquet_table_col twin gives: a caller can do nothing useful with a handle
that is one and not the other.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(parquet_table_row), | intent(in) | :: | self |
the row handle. |
.true. when it can still be used.
type :: parquet_table_row private type(parquet_table_cache), pointer :: cache => null() !! the table's column store. integer(int64) :: irow = 0 !! this row's 1-based index. integer(int64) :: gen = -1_int64 !! cache%generation when this handle was made. type(table_scope) :: scope !! the table's row scope, by value. contains procedure, private :: row_get_i32 !! %get specific for the i32 kind. procedure, private :: row_get_i64 !! %get specific for the i64 kind. procedure, private :: row_get_f32 !! %get specific for the f32 kind. procedure, private :: row_get_f64 !! %get specific for the f64 kind. procedure, private :: row_get_bool !! %get specific for the bool kind. procedure, private :: row_get_str !! %get specific for the str kind. procedure, private :: row_get_date !! %get specific for the date kind. procedure, private :: row_get_time !! %get specific for the time kind. procedure, private :: row_get_ts !! %get specific for the ts kind. procedure, private :: row_get_i32v !! %get specific for the i32v kind. procedure, private :: row_get_i64v !! %get specific for the i64v kind. procedure, private :: row_get_f32v !! %get specific for the f32v kind. procedure, private :: row_get_f64v !! %get specific for the f64v kind. procedure, private :: row_get_boolv !! %get specific for the boolv kind. procedure, private :: row_get_strv !! %get specific for the strv kind. procedure, private :: row_get_datev !! %get specific for the datev kind. procedure, private :: row_get_timev !! %get specific for the timev kind. procedure, private :: row_get_tsv !! %get specific for the tsv kind. procedure, private :: row_get_col_i32 !! %get specific, i32 kind, column by handle. procedure, private :: row_get_col_i64 !! %get specific, i64 kind, column by handle. procedure, private :: row_get_col_f32 !! %get specific, f32 kind, column by handle. procedure, private :: row_get_col_f64 !! %get specific, f64 kind, column by handle. procedure, private :: row_get_col_bool !! %get specific, bool kind, column by handle. procedure, private :: row_get_col_str !! %get specific, str kind, column by handle. procedure, private :: row_get_col_date !! %get specific, date kind, column by handle. procedure, private :: row_get_col_time !! %get specific, time kind, column by handle. procedure, private :: row_get_col_ts !! %get specific, ts kind, column by handle. procedure, private :: row_get_col_i32v !! %get specific, i32v kind, column by handle. procedure, private :: row_get_col_i64v !! %get specific, i64v kind, column by handle. procedure, private :: row_get_col_f32v !! %get specific, f32v kind, column by handle. procedure, private :: row_get_col_f64v !! %get specific, f64v kind, column by handle. procedure, private :: row_get_col_boolv !! %get specific, boolv kind, column by handle. procedure, private :: row_get_col_strv !! %get specific, strv kind, column by handle. procedure, private :: row_get_col_datev !! %get specific, datev kind, column by handle. procedure, private :: row_get_col_timev !! %get specific, timev kind, column by handle. procedure, private :: row_get_col_tsv !! %get specific, tsv kind, column by handle. !> Copies this row's value for a column into the caller's own variable, widening !! int32 -> int64 and float32 -> float64 exactly as the table's own %get does. The !! column may be named by a string or by a `parquet_table_col` handle; the handle !! form does no name lookup, which is what a loop over rows would otherwise repeat. generic :: get => row_get_i32, row_get_i64, row_get_f32, row_get_f64, row_get_bool, row_get_str, row_get_date, & row_get_time, row_get_ts, row_get_i32v, row_get_i64v, row_get_f32v, row_get_f64v, row_get_boolv, row_get_strv, & row_get_datev, row_get_timev, row_get_tsv, row_get_col_i32, row_get_col_i64, row_get_col_f32, row_get_col_f64, & row_get_col_bool, row_get_col_str, row_get_col_date, row_get_col_time, row_get_col_ts, row_get_col_i32v, & row_get_col_i64v, row_get_col_f32v, row_get_col_f64v, row_get_col_boolv, row_get_col_strv, row_get_col_datev, & row_get_col_timev, row_get_col_tsv procedure, private :: row_set_i32 !! %set specific for the i32 kind. procedure, private :: row_set_i64 !! %set specific for the i64 kind. procedure, private :: row_set_f32 !! %set specific for the f32 kind. procedure, private :: row_set_f64 !! %set specific for the f64 kind. procedure, private :: row_set_bool !! %set specific for the bool kind. procedure, private :: row_set_str !! %set specific for the str kind. procedure, private :: row_set_date !! %set specific for the date kind. procedure, private :: row_set_time !! %set specific for the time kind. procedure, private :: row_set_ts !! %set specific for the ts kind. procedure, private :: row_set_i32v !! %set specific for the i32v kind. procedure, private :: row_set_i64v !! %set specific for the i64v kind. procedure, private :: row_set_f32v !! %set specific for the f32v kind. procedure, private :: row_set_f64v !! %set specific for the f64v kind. procedure, private :: row_set_boolv !! %set specific for the boolv kind. procedure, private :: row_set_strv !! %set specific for the strv kind. procedure, private :: row_set_datev !! %set specific for the datev kind. procedure, private :: row_set_timev !! %set specific for the timev kind. procedure, private :: row_set_tsv !! %set specific for the tsv kind. procedure, private :: row_set_col_i32 !! %set specific, i32 kind, column by handle. procedure, private :: row_set_col_i64 !! %set specific, i64 kind, column by handle. procedure, private :: row_set_col_f32 !! %set specific, f32 kind, column by handle. procedure, private :: row_set_col_f64 !! %set specific, f64 kind, column by handle. procedure, private :: row_set_col_bool !! %set specific, bool kind, column by handle. procedure, private :: row_set_col_str !! %set specific, str kind, column by handle. procedure, private :: row_set_col_date !! %set specific, date kind, column by handle. procedure, private :: row_set_col_time !! %set specific, time kind, column by handle. procedure, private :: row_set_col_ts !! %set specific, ts kind, column by handle. procedure, private :: row_set_col_i32v !! %set specific, i32v kind, column by handle. procedure, private :: row_set_col_i64v !! %set specific, i64v kind, column by handle. procedure, private :: row_set_col_f32v !! %set specific, f32v kind, column by handle. procedure, private :: row_set_col_f64v !! %set specific, f64v kind, column by handle. procedure, private :: row_set_col_boolv !! %set specific, boolv kind, column by handle. procedure, private :: row_set_col_strv !! %set specific, strv kind, column by handle. procedure, private :: row_set_col_datev !! %set specific, datev kind, column by handle. procedure, private :: row_set_col_timev !! %set specific, timev kind, column by handle. procedure, private :: row_set_col_tsv !! %set specific, tsv kind, column by handle. !> Writes this row's value for a column. The kind must match the column's exactly !! (a write never widens), and writing a value CLEARS that row's null. The TABLE is !! updated -- a handle is a view of it, not a copy. The column may be named by a !! string or by a `parquet_table_col` handle. generic :: set => row_set_i32, row_set_i64, row_set_f32, row_set_f64, row_set_bool, row_set_str, row_set_date, & row_set_time, row_set_ts, row_set_i32v, row_set_i64v, row_set_f32v, row_set_f64v, row_set_boolv, row_set_strv, & row_set_datev, row_set_timev, row_set_tsv, row_set_col_i32, row_set_col_i64, row_set_col_f32, row_set_col_f64, & row_set_col_bool, row_set_col_str, row_set_col_date, row_set_col_time, row_set_col_ts, row_set_col_i32v, & row_set_col_i64v, row_set_col_f32v, row_set_col_f64v, row_set_col_boolv, row_set_col_strv, row_set_col_datev, & row_set_col_timev, row_set_col_tsv procedure, private :: row_ref_i32 !! %ref specific for the i32 kind. procedure, private :: row_ref_i64 !! %ref specific for the i64 kind. procedure, private :: row_ref_f32 !! %ref specific for the f32 kind. procedure, private :: row_ref_f64 !! %ref specific for the f64 kind. procedure, private :: row_ref_bool !! %ref specific for the bool kind. procedure, private :: row_ref_date !! %ref specific for the date kind. procedure, private :: row_ref_time !! %ref specific for the time kind. procedure, private :: row_ref_ts !! %ref specific for the ts kind. procedure, private :: row_ref_i32v !! %ref specific for the i32v kind. procedure, private :: row_ref_i64v !! %ref specific for the i64v kind. procedure, private :: row_ref_f32v !! %ref specific for the f32v kind. procedure, private :: row_ref_f64v !! %ref specific for the f64v kind. procedure, private :: row_ref_boolv !! %ref specific for the boolv kind. procedure, private :: row_ref_datev !! %ref specific for the datev kind. procedure, private :: row_ref_timev !! %ref specific for the timev kind. procedure, private :: row_ref_tsv !! %ref specific for the tsv kind. !> Points `p` at this row's storage: zero copy, writable, exact kind. A scalar !! column gives a scalar pointer, a vector column a pointer to that row's whole !! vector. The two string kinds have no %ref -- a packed variable-length store has !! no fixed slot to point at -- and the pointer dies with any structural change, !! exactly as the table's own %col pointers do. generic :: ref => row_ref_i32, row_ref_i64, row_ref_f32, row_ref_f64, row_ref_bool, row_ref_date, row_ref_time, & row_ref_ts, row_ref_i32v, row_ref_i64v, row_ref_f32v, row_ref_f64v, row_ref_boolv, row_ref_datev, row_ref_timev, & row_ref_tsv procedure, private :: row_is_null !! %is_null specific asking about the whole row. procedure, private :: row_is_null_elem !! %is_null specific asking about one element. !> Whether this row is null in a column, or -- given `e` -- element `e` of it. generic :: is_null => row_is_null, row_is_null_elem procedure :: index => row_index !! This row's 1-based index within the table. procedure :: is_valid => row_is_valid !! Whether the handle is attached AND still current. ! NO `final` -- see the type's own doc-comment. This is a decision, not an omission. end type parquet_table_row