1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// duckdb/main/appender.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/common/types/data_chunk.hpp"
12#include "duckdb/common/winapi.hpp"
13#include "duckdb/main/table_description.hpp"
14
15namespace duckdb {
16
17class ColumnDataCollection;
18class ClientContext;
19class DuckDB;
20class TableCatalogEntry;
21class Connection;
22
23enum class AppenderType : uint8_t {
24 LOGICAL, // Cast input -> LogicalType
25 PHYSICAL // Cast input -> PhysicalType
26};
27
28//! The Appender class can be used to append elements to a table.
29class BaseAppender {
30protected:
31 //! The amount of tuples that will be gathered in the column data collection before flushing
32 static constexpr const idx_t FLUSH_COUNT = STANDARD_VECTOR_SIZE * 100;
33
34 Allocator &allocator;
35 //! The append types
36 vector<LogicalType> types;
37 //! The buffered data for the append
38 unique_ptr<ColumnDataCollection> collection;
39 //! Internal chunk used for appends
40 DataChunk chunk;
41 //! The current column to append to
42 idx_t column = 0;
43 //! The type of the appender
44 AppenderType appender_type;
45
46protected:
47 DUCKDB_API BaseAppender(Allocator &allocator, AppenderType type);
48 DUCKDB_API BaseAppender(Allocator &allocator, vector<LogicalType> types, AppenderType type);
49
50public:
51 DUCKDB_API virtual ~BaseAppender();
52
53 //! Begins a new row append, after calling this the other AppendX() functions
54 //! should be called the correct amount of times. After that,
55 //! EndRow() should be called.
56 DUCKDB_API void BeginRow();
57 //! Finishes appending the current row.
58 DUCKDB_API void EndRow();
59
60 // Append functions
61 template <class T>
62 void Append(T value) {
63 throw Exception("Undefined type for Appender::Append!");
64 }
65
66 DUCKDB_API void Append(const char *value, uint32_t length);
67
68 // prepared statements
69 template <typename... Args>
70 void AppendRow(Args... args) {
71 BeginRow();
72 AppendRowRecursive(args...);
73 }
74
75 //! Commit the changes made by the appender.
76 DUCKDB_API void Flush();
77 //! Flush the changes made by the appender and close it. The appender cannot be used after this point
78 DUCKDB_API void Close();
79
80 vector<LogicalType> &GetTypes() {
81 return types;
82 }
83 idx_t CurrentColumn() {
84 return column;
85 }
86 DUCKDB_API void AppendDataChunk(DataChunk &value);
87
88protected:
89 void Destructor();
90 virtual void FlushInternal(ColumnDataCollection &collection) = 0;
91 void InitializeChunk();
92 void FlushChunk();
93
94 template <class T>
95 void AppendValueInternal(T value);
96 template <class SRC, class DST>
97 void AppendValueInternal(Vector &vector, SRC input);
98 template <class SRC, class DST>
99 void AppendDecimalValueInternal(Vector &vector, SRC input);
100
101 void AppendRowRecursive() {
102 EndRow();
103 }
104
105 template <typename T, typename... Args>
106 void AppendRowRecursive(T value, Args... args) {
107 Append<T>(value);
108 AppendRowRecursive(args...);
109 }
110
111 void AppendValue(const Value &value);
112};
113
114class Appender : public BaseAppender {
115 //! A reference to a database connection that created this appender
116 shared_ptr<ClientContext> context;
117 //! The table description (including column names)
118 unique_ptr<TableDescription> description;
119
120public:
121 DUCKDB_API Appender(Connection &con, const string &schema_name, const string &table_name);
122 DUCKDB_API Appender(Connection &con, const string &table_name);
123 DUCKDB_API ~Appender() override;
124
125protected:
126 void FlushInternal(ColumnDataCollection &collection) override;
127};
128
129class InternalAppender : public BaseAppender {
130 //! The client context
131 ClientContext &context;
132 //! The internal table entry to append to
133 TableCatalogEntry &table;
134
135public:
136 DUCKDB_API InternalAppender(ClientContext &context, TableCatalogEntry &table);
137 DUCKDB_API ~InternalAppender() override;
138
139protected:
140 void FlushInternal(ColumnDataCollection &collection) override;
141};
142
143template <>
144DUCKDB_API void BaseAppender::Append(bool value);
145template <>
146DUCKDB_API void BaseAppender::Append(int8_t value);
147template <>
148DUCKDB_API void BaseAppender::Append(int16_t value);
149template <>
150DUCKDB_API void BaseAppender::Append(int32_t value);
151template <>
152DUCKDB_API void BaseAppender::Append(int64_t value);
153template <>
154DUCKDB_API void BaseAppender::Append(hugeint_t value);
155template <>
156DUCKDB_API void BaseAppender::Append(uint8_t value);
157template <>
158DUCKDB_API void BaseAppender::Append(uint16_t value);
159template <>
160DUCKDB_API void BaseAppender::Append(uint32_t value);
161template <>
162DUCKDB_API void BaseAppender::Append(uint64_t value);
163template <>
164DUCKDB_API void BaseAppender::Append(float value);
165template <>
166DUCKDB_API void BaseAppender::Append(double value);
167template <>
168DUCKDB_API void BaseAppender::Append(date_t value);
169template <>
170DUCKDB_API void BaseAppender::Append(dtime_t value);
171template <>
172DUCKDB_API void BaseAppender::Append(timestamp_t value);
173template <>
174DUCKDB_API void BaseAppender::Append(interval_t value);
175template <>
176DUCKDB_API void BaseAppender::Append(const char *value);
177template <>
178DUCKDB_API void BaseAppender::Append(string_t value);
179template <>
180DUCKDB_API void BaseAppender::Append(Value value);
181template <>
182DUCKDB_API void BaseAppender::Append(std::nullptr_t value);
183
184} // namespace duckdb
185