| 1 | #include "duckdb/common/field_writer.hpp" |
| 2 | |
| 3 | namespace duckdb { |
| 4 | |
| 5 | //===--------------------------------------------------------------------===// |
| 6 | // Field Writer |
| 7 | //===--------------------------------------------------------------------===// |
| 8 | FieldWriter::FieldWriter(Serializer &serializer_p) |
| 9 | : serializer(serializer_p), buffer(make_uniq<BufferedSerializer>()), field_count(0), finalized(false) { |
| 10 | buffer->SetVersion(serializer.GetVersion()); |
| 11 | buffer->is_query_plan = serializer.is_query_plan; |
| 12 | } |
| 13 | |
| 14 | FieldWriter::~FieldWriter() { |
| 15 | if (Exception::UncaughtException()) { |
| 16 | return; |
| 17 | } |
| 18 | D_ASSERT(finalized); |
| 19 | // finalize should always have been called, unless this is destroyed as part of stack unwinding |
| 20 | D_ASSERT(!buffer); |
| 21 | } |
| 22 | |
| 23 | void FieldWriter::WriteData(const_data_ptr_t buffer_ptr, idx_t write_size) { |
| 24 | D_ASSERT(buffer); |
| 25 | buffer->WriteData(buffer: buffer_ptr, write_size); |
| 26 | } |
| 27 | |
| 28 | template <> |
| 29 | void FieldWriter::Write(const string &val) { |
| 30 | Write<uint32_t>(element: (uint32_t)val.size()); |
| 31 | if (!val.empty()) { |
| 32 | WriteData(buffer_ptr: const_data_ptr_cast(src: val.c_str()), write_size: val.size()); |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | void FieldWriter::Finalize() { |
| 37 | D_ASSERT(buffer); |
| 38 | D_ASSERT(!finalized); |
| 39 | finalized = true; |
| 40 | serializer.Write<uint32_t>(element: field_count); |
| 41 | serializer.Write<uint64_t>(element: buffer->blob.size); |
| 42 | serializer.WriteData(buffer: buffer->blob.data.get(), write_size: buffer->blob.size); |
| 43 | |
| 44 | buffer.reset(); |
| 45 | } |
| 46 | |
| 47 | //===--------------------------------------------------------------------===// |
| 48 | // Field Deserializer |
| 49 | //===--------------------------------------------------------------------===// |
| 50 | FieldDeserializer::FieldDeserializer(Deserializer &root) : root(root), remaining_data(idx_t(-1)) { |
| 51 | SetVersion(root.GetVersion()); |
| 52 | } |
| 53 | |
| 54 | void FieldDeserializer::ReadData(data_ptr_t buffer, idx_t read_size) { |
| 55 | D_ASSERT(remaining_data != idx_t(-1)); |
| 56 | D_ASSERT(read_size <= remaining_data); |
| 57 | root.ReadData(buffer, read_size); |
| 58 | remaining_data -= read_size; |
| 59 | } |
| 60 | |
| 61 | idx_t FieldDeserializer::RemainingData() { |
| 62 | return remaining_data; |
| 63 | } |
| 64 | |
| 65 | void FieldDeserializer::SetRemainingData(idx_t remaining_data) { |
| 66 | this->remaining_data = remaining_data; |
| 67 | } |
| 68 | |
| 69 | //===--------------------------------------------------------------------===// |
| 70 | // Field Reader |
| 71 | //===--------------------------------------------------------------------===// |
| 72 | FieldReader::FieldReader(Deserializer &source_p) : source(source_p), field_count(0), finalized(false) { |
| 73 | max_field_count = source_p.Read<uint32_t>(); |
| 74 | total_size = source_p.Read<uint64_t>(); |
| 75 | D_ASSERT(max_field_count > 0); |
| 76 | source.SetRemainingData(total_size); |
| 77 | } |
| 78 | |
| 79 | FieldReader::~FieldReader() { |
| 80 | if (Exception::UncaughtException()) { |
| 81 | return; |
| 82 | } |
| 83 | D_ASSERT(finalized); |
| 84 | } |
| 85 | |
| 86 | void FieldReader::Finalize() { |
| 87 | D_ASSERT(!finalized); |
| 88 | finalized = true; |
| 89 | if (field_count < max_field_count) { |
| 90 | // we can handle this case by calling source.ReadData(buffer, source.RemainingData()) |
| 91 | throw SerializationException("Not all fields were read. This file might have been written with a newer version " |
| 92 | "of DuckDB and is incompatible with this version of DuckDB." ); |
| 93 | } |
| 94 | D_ASSERT(source.RemainingData() == 0); |
| 95 | } |
| 96 | |
| 97 | } // namespace duckdb |
| 98 | |