Bulk-appends a character array, trimming each element's trailing blanks -- the appending
counterpart of build_from's character form, sharing its packing walk and existing for the
same reason: parquet_column%append_values on a string column used one %append_string call
per element. See build_from_character for why the byte-view copy is what makes this fast
and why len_trim must stay on the element view.
is_null, when present, appends those elements as zero-width nulls and ignores their
values entry.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(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. |
subroutine parquet_string_column_append_values(self, values, is_null) type(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. integer(int64) :: n, k, nchars, nnull, base_rows integer, allocatable :: lens(:) ! Stands in for `self%data` when the column holds no bytes at all. `ensure_data_cap` ! deliberately allocates nothing for a zero-byte payload, and `pack_character_bytes` takes ! `dst` as an ordinary (non-allocatable) dummy -- so passing `self%data` there unallocated ! is not conforming, and nagfor's -C=array aborts on it ("ALLOCATABLE SELF%DATA is not ! currently allocated") where gfortran runs on silently. Reached whenever every element is ! blank or null. Here it needs the column to be empty too, since an ! earlier append will already have allocated the payload. ! Handing the same routine a real one-byte array instead keeps ONE implementation of the ! offset walk: with every `lens(k)` zero it writes offsets and never touches `dst`. character(len=1) :: no_bytes(1) n = size(values, kind=int64) if (present(is_null)) then if (size(is_null, kind=int64) /= n) then error stop EP//"append_values: is_null must have the same length as values" end if end if if (n <= 0_int64) return allocate(lens(n)) nchars = 0_int64 nnull = 0_int64 if (present(is_null)) then do k = 1_int64, n if (is_null(k)) then lens(k) = 0 nnull = nnull + 1_int64 else lens(k) = len_trim(values(k)) nchars = nchars + int(lens(k), int64) end if end do else do k = 1_int64, n lens(k) = len_trim(values(k)) nchars = nchars + int(lens(k), int64) end do end if base_rows = self%nrows call ensure_offsets_cap(self, base_rows + n) if (nchars > 0_int64) call ensure_data_cap(self, self%nchars + nchars) if (allocated(self%data)) then call pack_character_bytes(values, self%data, self%offsets, lens, n, len(values), base_rows) else call pack_character_bytes(values, no_bytes, self%offsets, lens, n, len(values), base_rows) end if if (nnull > 0_int64) then self%has_nulls = .true. call ensure_validity_cap(self, base_rows + n) do k = 1_int64, n if (is_null(k)) call set_bit_null(self, base_rows + k) end do self%n_null = self%n_null + nnull else if (self%has_nulls) then ! The column already tracks validity, so the appended rows need their bits written ! valid rather than left at whatever the grown buffer holds -- the same step ! `append_buffers` takes for exactly this case. call ensure_validity_cap(self, base_rows + n) call fill_validity_valid(self, base_rows + 1_int64, n) end if self%nrows = base_rows + n self%nchars = self%nchars + nchars end subroutine parquet_string_column_append_values