blob: 5779d5e7d34febd3149f36ebb9f36b3dd6397490 [file] [view]
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Nulls
A non-aligned timeseries stores only the `(timestamp, value)` points that exist. Its Pages do not
contain null markers.
An aligned value column records nulls in the bitmap of each Value Page:
```text
AlignedValuePagePayload :=
int32 position_count
byte present_bitmap[ceil(position_count / 8)]
byte encoded_non_null_values[remaining bytes]
```
Position `i` corresponds to bit `7 - (i mod 8)` of `present_bitmap[i / 8]`:
- A set bit means that the position has a value.
- A clear bit means that the position is null.
The encoded value stream contains only values whose bitmap bits are set, in position order.
`position_count` equals the number of timestamps in the corresponding Time Page.
For example, with `position_count = 10`, bitmap bytes `10110000 01000000` indicate values at
positions `0`, `2`, `3`, and `9`. The value decoder therefore produces four values and places them
at those positions; the remaining six positions are null. Unused low-order bits in the final byte
are not logical positions and are ignored.
For a non-empty Value Page the following invariants hold:
```text
bitmap_bytes = ceil(position_count / 8)
decoded_value_count = popcount(present_bitmap over position_count bits)
position_count = decoded_timestamp_count of the corresponding Time Page
```
A mismatch is structural corruption; the reader must not infer additional positions from trailing
bitmap bits or encoded values.
If an entire Value Page is null, the Page consists only of an `uncompressed_size` equal to zero:
```text
EmptyAlignedValuePage := UVarInt(0)
```
An empty Page has no `compressed_size`, Statistics, bitmap, or value stream. Its position count is
obtained from the corresponding Time Page.
An empty Value Page preserves its position in the Page sequence, so subsequent Value Pages still
match the correct Time Pages. An absent Value Chunk has no physical column for that aligned Chunk
set. A Value Chunk with `data_size = 0` is a third case: its Header exists, but it contains no
Pages. These cases must be distinguished when walking the aligned Chunk set.