1 | #include "duckdb/execution/operator/persistent/physical_insert.hpp" |
2 | |
3 | #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" |
4 | #include "duckdb/common/types/chunk_collection.hpp" |
5 | #include "duckdb/common/vector_operations/vector_operations.hpp" |
6 | #include "duckdb/execution/expression_executor.hpp" |
7 | #include "duckdb/storage/data_table.hpp" |
8 | |
9 | using namespace duckdb; |
10 | using namespace std; |
11 | |
12 | void PhysicalInsert::GetChunkInternal(ClientContext &context, DataChunk &chunk, PhysicalOperatorState *state) { |
13 | |
14 | int64_t insert_count = 0; |
15 | // create the chunk to insert from |
16 | DataChunk insert_chunk; |
17 | auto types = table->GetTypes(); |
18 | |
19 | // initialize executor for bound default expressions |
20 | ExpressionExecutor default_executor(bound_defaults); |
21 | |
22 | insert_chunk.Initialize(types); |
23 | while (true) { |
24 | // scan the children for chunks to insert |
25 | children[0]->GetChunk(context, state->child_chunk, state->child_state.get()); |
26 | if (state->child_chunk.size() == 0) { |
27 | break; |
28 | } |
29 | auto &chunk = state->child_chunk; |
30 | |
31 | chunk.Normalify(); |
32 | default_executor.SetChunk(chunk); |
33 | |
34 | insert_chunk.Reset(); |
35 | insert_chunk.SetCardinality(chunk); |
36 | if (column_index_map.size() > 0) { |
37 | // columns specified by the user, use column_index_map |
38 | for (idx_t i = 0; i < table->columns.size(); i++) { |
39 | if (column_index_map[i] == INVALID_INDEX) { |
40 | // insert default value |
41 | default_executor.ExecuteExpression(i, insert_chunk.data[i]); |
42 | } else { |
43 | // get value from child chunk |
44 | assert((idx_t)column_index_map[i] < chunk.column_count()); |
45 | assert(insert_chunk.data[i].type == chunk.data[column_index_map[i]].type); |
46 | insert_chunk.data[i].Reference(chunk.data[column_index_map[i]]); |
47 | } |
48 | } |
49 | } else { |
50 | // no columns specified, just append directly |
51 | for (idx_t i = 0; i < insert_chunk.column_count(); i++) { |
52 | assert(insert_chunk.data[i].type == chunk.data[i].type); |
53 | insert_chunk.data[i].Reference(chunk.data[i]); |
54 | } |
55 | } |
56 | table->storage->Append(*table, context, insert_chunk); |
57 | insert_count += chunk.size(); |
58 | } |
59 | |
60 | chunk.SetCardinality(1); |
61 | chunk.SetValue(0, 0, Value::BIGINT(insert_count)); |
62 | |
63 | state->finished = true; |
64 | } |
65 | |