parquet_string_column_append_values Subroutine

public subroutine parquet_string_column_append_values(self, values, is_null)

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.

Arguments

Type IntentOptional 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.


Source Code

    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