duckdb 0.3.2-dev996.0 → 0.3.3-dev108.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright 2018 DuckDB Contributors (see https://github.com/duckdb/duckdb/graphs/contributors)
2
+ Copyright 2018-2022 Stichting DuckDB Foundation
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
5
 
@@ -7069,6 +7069,57 @@ private:
7069
7069
 
7070
7070
 
7071
7071
 
7072
+
7073
+
7074
+ namespace duckdb {
7075
+ class ParquetDecodeUtils {
7076
+
7077
+ public:
7078
+ template <class T>
7079
+ static T ZigzagToInt(const T n) {
7080
+ return (n >> 1) ^ -(n & 1);
7081
+ }
7082
+
7083
+ static const uint32_t BITPACK_MASKS[];
7084
+ static const uint8_t BITPACK_DLEN;
7085
+
7086
+ template <typename T>
7087
+ static uint32_t BitUnpack(ByteBuffer &buffer, uint8_t &bitpack_pos, T *dest, uint32_t count, uint8_t width) {
7088
+ auto mask = BITPACK_MASKS[width];
7089
+
7090
+ for (uint32_t i = 0; i < count; i++) {
7091
+ T val = (buffer.get<uint8_t>() >> bitpack_pos) & mask;
7092
+ bitpack_pos += width;
7093
+ while (bitpack_pos > BITPACK_DLEN) {
7094
+ buffer.inc(1);
7095
+ val |= (buffer.get<uint8_t>() << (BITPACK_DLEN - (bitpack_pos - width))) & mask;
7096
+ bitpack_pos -= BITPACK_DLEN;
7097
+ }
7098
+ dest[i] = val;
7099
+ }
7100
+ return count;
7101
+ }
7102
+
7103
+ template <class T>
7104
+ static T VarintDecode(ByteBuffer &buf) {
7105
+ T result = 0;
7106
+ uint8_t shift = 0;
7107
+ while (true) {
7108
+ auto byte = buf.read<uint8_t>();
7109
+ result |= (byte & 127) << shift;
7110
+ if ((byte & 128) == 0)
7111
+ break;
7112
+ shift += 7;
7113
+ if (shift > sizeof(T) * 8) {
7114
+ throw std::runtime_error("Varint-decoding found too large number");
7115
+ }
7116
+ }
7117
+ return result;
7118
+ }
7119
+ };
7120
+ } // namespace duckdb
7121
+
7122
+
7072
7123
  namespace duckdb {
7073
7124
 
7074
7125
  class RleBpDecoder {
@@ -7098,7 +7149,8 @@ public:
7098
7149
  values_read += repeat_batch;
7099
7150
  } else if (literal_count_ > 0) {
7100
7151
  uint32_t literal_batch = MinValue(batch_size - values_read, static_cast<uint32_t>(literal_count_));
7101
- uint32_t actual_read = BitUnpack<T>(values + values_read, literal_batch);
7152
+ uint32_t actual_read = ParquetDecodeUtils::BitUnpack<T>(buffer_, bitpack_pos, values + values_read,
7153
+ literal_batch, bit_width_);
7102
7154
  if (literal_batch != actual_read) {
7103
7155
  throw std::runtime_error("Did not find enough values");
7104
7156
  }
@@ -7140,26 +7192,7 @@ private:
7140
7192
  uint8_t byte_encoded_len;
7141
7193
  uint32_t max_val;
7142
7194
 
7143
- int8_t bitpack_pos = 0;
7144
-
7145
- // this is slow but whatever, calls are rare
7146
- uint32_t VarintDecode() {
7147
- uint32_t result = 0;
7148
- uint8_t shift = 0;
7149
- uint8_t len = 0;
7150
- while (true) {
7151
- auto byte = buffer_.read<uint8_t>();
7152
- len++;
7153
- result |= (byte & 127) << shift;
7154
- if ((byte & 128) == 0)
7155
- break;
7156
- shift += 7;
7157
- if (shift > 32) {
7158
- throw std::runtime_error("Varint-decoding found too large number");
7159
- }
7160
- }
7161
- return result;
7162
- }
7195
+ uint8_t bitpack_pos = 0;
7163
7196
 
7164
7197
  /// Fills literal_count_ and repeat_count_ with next values. Returns false if there
7165
7198
  /// are no more.
@@ -7171,7 +7204,7 @@ private:
7171
7204
  buffer_.inc(1);
7172
7205
  bitpack_pos = 0;
7173
7206
  }
7174
- auto indicator_value = VarintDecode();
7207
+ auto indicator_value = ParquetDecodeUtils::VarintDecode<uint32_t>(buffer_);
7175
7208
 
7176
7209
  // lsb indicates if it is a literal run or repeated run
7177
7210
  bool is_literal = indicator_value & 1;
@@ -7192,28 +7225,121 @@ private:
7192
7225
  // TODO complain if we run out of buffer
7193
7226
  return true;
7194
7227
  }
7228
+ };
7229
+ } // namespace duckdb
7230
+
7195
7231
 
7196
- // somewhat optimized implementation that avoids non-alignment
7197
7232
 
7198
- static const uint32_t BITPACK_MASKS[];
7199
- static const uint8_t BITPACK_DLEN;
7233
+
7234
+ namespace duckdb {
7235
+ class DbpDecoder {
7236
+ public:
7237
+ DbpDecoder(const uint8_t *buffer, uint32_t buffer_len) : buffer_((char *)buffer, buffer_len) {
7238
+
7239
+ //<block size in values> <number of miniblocks in a block> <total value count> <first value>
7240
+ // overall header
7241
+ block_value_count = ParquetDecodeUtils::VarintDecode<uint64_t>(buffer_);
7242
+ miniblocks_per_block = ParquetDecodeUtils::VarintDecode<uint64_t>(buffer_);
7243
+ total_value_count = ParquetDecodeUtils::VarintDecode<uint64_t>(buffer_);
7244
+ start_value = ParquetDecodeUtils::ZigzagToInt(ParquetDecodeUtils::VarintDecode<int64_t>(buffer_));
7245
+
7246
+ // some derivatives
7247
+ values_per_miniblock = block_value_count / miniblocks_per_block;
7248
+ miniblock_bit_widths = std::unique_ptr<uint8_t[]>(new data_t[miniblocks_per_block]);
7249
+
7250
+ // init state to something sane
7251
+ values_left_in_block = 0;
7252
+ values_left_in_miniblock = 0;
7253
+ miniblock_offset = 0;
7254
+ min_delta = 0;
7255
+ bitpack_pos = 0;
7256
+ is_first_value = true;
7257
+ };
7258
+
7259
+ ByteBuffer BufferPtr() {
7260
+ if (bitpack_pos != 0) {
7261
+ buffer_.inc(1);
7262
+ bitpack_pos = 0;
7263
+ }
7264
+ return buffer_;
7265
+ }
7200
7266
 
7201
7267
  template <typename T>
7202
- uint32_t BitUnpack(T *dest, uint32_t count) {
7203
- auto mask = BITPACK_MASKS[bit_width_];
7268
+ void GetBatch(char *values_target_ptr, uint32_t batch_size) {
7269
+ auto values = (T *)values_target_ptr;
7204
7270
 
7205
- for (uint32_t i = 0; i < count; i++) {
7206
- T val = (buffer_.get<uint8_t>() >> bitpack_pos) & mask;
7207
- bitpack_pos += bit_width_;
7208
- while (bitpack_pos > BITPACK_DLEN) {
7209
- buffer_.inc(1);
7210
- val |= (buffer_.get<uint8_t>() << (BITPACK_DLEN - (bitpack_pos - bit_width_))) & mask;
7211
- bitpack_pos -= BITPACK_DLEN;
7271
+ if (batch_size == 0) {
7272
+ return;
7273
+ }
7274
+ idx_t value_offset = 0;
7275
+
7276
+ if (is_first_value) {
7277
+ values[0] = start_value;
7278
+ value_offset++;
7279
+ is_first_value = false;
7280
+ }
7281
+
7282
+ if (total_value_count == 1) { // I guess it's a special case
7283
+ if (batch_size > 1) {
7284
+ throw std::runtime_error("DBP decode did not find enough values (have 1)");
7212
7285
  }
7213
- dest[i] = val;
7286
+ return;
7214
7287
  }
7215
- return count;
7288
+
7289
+ while (value_offset < batch_size) {
7290
+ if (values_left_in_block == 0) { // need to open new block
7291
+ if (bitpack_pos > 0) { // have to eat the leftovers if any
7292
+ buffer_.inc(1);
7293
+ }
7294
+ min_delta = ParquetDecodeUtils::ZigzagToInt(ParquetDecodeUtils::VarintDecode<uint64_t>(buffer_));
7295
+ for (idx_t miniblock_idx = 0; miniblock_idx < miniblocks_per_block; miniblock_idx++) {
7296
+ miniblock_bit_widths[miniblock_idx] = buffer_.read<uint8_t>();
7297
+ // TODO what happens if width is 0?
7298
+ }
7299
+ values_left_in_block = block_value_count;
7300
+ miniblock_offset = 0;
7301
+ bitpack_pos = 0;
7302
+ values_left_in_miniblock = values_per_miniblock;
7303
+ }
7304
+ if (values_left_in_miniblock == 0) {
7305
+ miniblock_offset++;
7306
+ values_left_in_miniblock = values_per_miniblock;
7307
+ }
7308
+
7309
+ auto read_now = MinValue(values_left_in_miniblock, (idx_t)batch_size - value_offset);
7310
+ ParquetDecodeUtils::BitUnpack<T>(buffer_, bitpack_pos, &values[value_offset], read_now,
7311
+ miniblock_bit_widths[miniblock_offset]);
7312
+ for (idx_t i = value_offset; i < value_offset + read_now; i++) {
7313
+ values[i] = ((i == 0) ? start_value : values[i - 1]) + min_delta + values[i];
7314
+ }
7315
+ value_offset += read_now;
7316
+ values_left_in_miniblock -= read_now;
7317
+ values_left_in_block -= read_now;
7318
+ }
7319
+
7320
+ if (value_offset != batch_size) {
7321
+ throw std::runtime_error("DBP decode did not find enough values");
7322
+ }
7323
+ start_value = values[batch_size - 1];
7216
7324
  }
7325
+
7326
+ private:
7327
+ ByteBuffer buffer_;
7328
+ idx_t block_value_count;
7329
+ idx_t miniblocks_per_block;
7330
+ idx_t total_value_count;
7331
+ int64_t start_value;
7332
+ idx_t values_per_miniblock;
7333
+
7334
+ std::unique_ptr<uint8_t[]> miniblock_bit_widths;
7335
+ idx_t values_left_in_block;
7336
+ idx_t values_left_in_miniblock;
7337
+ idx_t miniblock_offset;
7338
+ int64_t min_delta;
7339
+
7340
+ bool is_first_value;
7341
+
7342
+ uint8_t bitpack_pos;
7217
7343
  };
7218
7344
  } // namespace duckdb
7219
7345
 
@@ -7325,6 +7451,7 @@ private:
7325
7451
  void PrepareRead(parquet_filter_t &filter);
7326
7452
  void PreparePage(idx_t compressed_page_size, idx_t uncompressed_page_size);
7327
7453
  void PrepareDataPage(PageHeader &page_hdr);
7454
+ void PreparePageV2(PageHeader &page_hdr);
7328
7455
 
7329
7456
  const duckdb_parquet::format::ColumnChunk *chunk;
7330
7457
 
@@ -7340,6 +7467,7 @@ private:
7340
7467
  unique_ptr<RleBpDecoder> dict_decoder;
7341
7468
  unique_ptr<RleBpDecoder> defined_decoder;
7342
7469
  unique_ptr<RleBpDecoder> repeated_decoder;
7470
+ unique_ptr<DbpDecoder> dbp_decoder;
7343
7471
 
7344
7472
  // dummies for Skip()
7345
7473
  parquet_filter_t none_filter;