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 | |