| 56 | } |
| 57 | |
| 58 | void RowTableMetadata::FromColumnMetadataVector( |
| 59 | const std::vector<KeyColumnMetadata>& cols, int in_row_alignment, |
| 60 | int in_string_alignment) { |
| 61 | column_metadatas.resize(cols.size()); |
| 62 | for (size_t i = 0; i < cols.size(); ++i) { |
| 63 | column_metadatas[i] = cols[i]; |
| 64 | } |
| 65 | |
| 66 | const auto num_cols = static_cast<uint32_t>(cols.size()); |
| 67 | |
| 68 | // Sort columns. |
| 69 | // |
| 70 | // Columns are sorted based on the size in bytes of their fixed-length part. |
| 71 | // For the varying-length column, the fixed-length part is the 32-bit field storing |
| 72 | // cumulative length of varying-length fields. This is to make the memory access of |
| 73 | // each individual column within the encoded row alignment-friendly. |
| 74 | // |
| 75 | // The rules are: |
| 76 | // |
| 77 | // a) Boolean column, marked with fixed-length 0, is considered to have fixed-length |
| 78 | // part of 1 byte. |
| 79 | // |
| 80 | // b) Columns with fixed-length part being power of 2 or multiple of row |
| 81 | // alignment precede other columns. They are sorted in decreasing order of the size of |
| 82 | // their fixed-length part. |
| 83 | // |
| 84 | // c) Fixed-length columns precede varying-length columns when |
| 85 | // both have the same size fixed-length part. |
| 86 | // |
| 87 | column_order.resize(num_cols); |
| 88 | for (uint32_t i = 0; i < num_cols; ++i) { |
| 89 | column_order[i] = i; |
| 90 | } |
| 91 | std::sort( |
| 92 | column_order.begin(), column_order.end(), [&cols](uint32_t left, uint32_t right) { |
| 93 | bool is_left_pow2 = |
| 94 | !cols[left].is_fixed_length || std::popcount(cols[left].fixed_length) <= 1; |
| 95 | bool is_right_pow2 = |
| 96 | !cols[right].is_fixed_length || std::popcount(cols[right].fixed_length) <= 1; |
| 97 | bool is_left_fixedlen = cols[left].is_fixed_length; |
| 98 | bool is_right_fixedlen = cols[right].is_fixed_length; |
| 99 | uint32_t width_left = |
| 100 | cols[left].is_fixed_length ? cols[left].fixed_length : sizeof(uint32_t); |
| 101 | uint32_t width_right = |
| 102 | cols[right].is_fixed_length ? cols[right].fixed_length : sizeof(uint32_t); |
| 103 | if (is_left_pow2 != is_right_pow2) { |
| 104 | return is_left_pow2; |
| 105 | } |
| 106 | if (!is_left_pow2) { |
| 107 | return left < right; |
| 108 | } |
| 109 | if (width_left != width_right) { |
| 110 | return width_left > width_right; |
| 111 | } |
| 112 | if (is_left_fixedlen != is_right_fixedlen) { |
| 113 | return is_left_fixedlen; |
| 114 | } |
| 115 | return left < right; |