duckdb 0.5.2-dev1460.0 → 0.5.2-dev1468.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.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
4
  "types": "./lib/duckdb.d.ts",
5
- "version": "0.5.2-dev1460.0",
5
+ "version": "0.5.2-dev1468.0",
6
6
  "description": "DuckDB node.js API",
7
7
  "gypfile": true,
8
8
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -80586,7 +80586,7 @@ public:
80586
80586
  idx_t current_index;
80587
80587
  TableAppendState current_append_state;
80588
80588
  unique_ptr<RowGroupCollection> current_collection;
80589
- unique_ptr<OptimisticDataWriter> writer;
80589
+ OptimisticDataWriter *writer;
80590
80590
  bool written_to_disk;
80591
80591
 
80592
80592
  void FlushToDisk() {
@@ -80636,16 +80636,17 @@ SinkResultType PhysicalBatchInsert::Sink(ExecutionContext &context, GlobalSinkSt
80636
80636
  PhysicalInsert::ResolveDefaults(table, chunk, column_index_map, lstate.default_executor, lstate.insert_chunk);
80637
80637
 
80638
80638
  if (!lstate.current_collection) {
80639
+ lock_guard<mutex> l(gstate.lock);
80639
80640
  // no collection yet: create a new one
80640
80641
  lstate.CreateNewCollection(table, insert_types);
80641
- lstate.writer = make_unique<OptimisticDataWriter>(gstate.table->storage.get());
80642
+ lstate.writer = gstate.table->storage->CreateOptimisticWriter(context.client);
80642
80643
  } else if (lstate.current_index != lstate.batch_index) {
80643
80644
  // batch index has changed: move the old collection to the global state and create a new collection
80644
80645
  TransactionData tdata(0, 0);
80645
80646
  lstate.current_collection->FinalizeAppend(tdata, lstate.current_append_state);
80646
80647
  lstate.FlushToDisk();
80647
80648
 
80648
- gstate.AddCollection(context.client, lstate.current_index, move(lstate.current_collection), lstate.writer.get(),
80649
+ gstate.AddCollection(context.client, lstate.current_index, move(lstate.current_collection), lstate.writer,
80649
80650
  &lstate.written_to_disk);
80650
80651
  lstate.CreateNewCollection(table, insert_types);
80651
80652
  }
@@ -80715,7 +80716,7 @@ SinkFinalizeType PhysicalBatchInsert::Finalize(Pipeline &pipeline, Event &event,
80715
80716
  // now that we have created all of the mergers, perform the actual merging
80716
80717
  vector<unique_ptr<RowGroupCollection>> final_collections;
80717
80718
  final_collections.reserve(mergers.size());
80718
- auto writer = make_unique<OptimisticDataWriter>(&storage);
80719
+ auto writer = storage.CreateOptimisticWriter(context);
80719
80720
  for (auto &merger : mergers) {
80720
80721
  final_collections.push_back(merger->Flush(*writer));
80721
80722
  }
@@ -81415,7 +81416,7 @@ public:
81415
81416
  ExpressionExecutor default_executor;
81416
81417
  TableAppendState local_append_state;
81417
81418
  unique_ptr<RowGroupCollection> local_collection;
81418
- unique_ptr<OptimisticDataWriter> writer;
81419
+ OptimisticDataWriter *writer;
81419
81420
  };
81420
81421
 
81421
81422
  unique_ptr<GlobalSinkState> PhysicalInsert::GetGlobalSinkState(ClientContext &context) const {
@@ -81494,13 +81495,14 @@ SinkResultType PhysicalInsert::Sink(ExecutionContext &context, GlobalSinkState &
81494
81495
  D_ASSERT(!return_chunk);
81495
81496
  // parallel append
81496
81497
  if (!lstate.local_collection) {
81498
+ lock_guard<mutex> l(gstate.lock);
81497
81499
  auto &table_info = table->storage->info;
81498
81500
  auto &block_manager = TableIOManager::Get(*table->storage).GetBlockManagerForRowData();
81499
81501
  lstate.local_collection =
81500
81502
  make_unique<RowGroupCollection>(table_info, block_manager, insert_types, MAX_ROW_ID);
81501
81503
  lstate.local_collection->InitializeEmpty();
81502
81504
  lstate.local_collection->InitializeAppend(lstate.local_append_state);
81503
- lstate.writer = make_unique<OptimisticDataWriter>(gstate.table->storage.get());
81505
+ lstate.writer = gstate.table->storage->CreateOptimisticWriter(context.client);
81504
81506
  }
81505
81507
  table->storage->VerifyAppendConstraints(*table, context.client, lstate.insert_chunk);
81506
81508
  auto new_row_group = lstate.local_collection->Append(lstate.insert_chunk, lstate.local_append_state);
@@ -87227,11 +87229,6 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalInsert &op
87227
87229
 
87228
87230
  bool parallel_streaming_insert = !PreserveInsertionOrder(*plan);
87229
87231
  bool use_batch_index = UseBatchIndex(*plan);
87230
- if (!op.table->storage->info->indexes.Empty()) {
87231
- // not for tables with indexes currently
87232
- parallel_streaming_insert = false;
87233
- use_batch_index = false;
87234
- }
87235
87232
  if (op.return_chunk) {
87236
87233
  // not supported for RETURNING (yet?)
87237
87234
  parallel_streaming_insert = false;
@@ -198132,6 +198129,9 @@ public:
198132
198129
  bool IsRootBlock(block_id_t root) override {
198133
198130
  throw InternalException("Cannot perform IO in in-memory database!");
198134
198131
  }
198132
+ void MarkBlockAsFree(block_id_t block_id) override {
198133
+ throw InternalException("Cannot perform IO in in-memory database!");
198134
+ }
198135
198135
  void MarkBlockAsModified(block_id_t block_id) override {
198136
198136
  throw InternalException("Cannot perform IO in in-memory database!");
198137
198137
  }
@@ -208337,6 +208337,11 @@ void DataTable::FinalizeLocalAppend(LocalAppendState &state) {
208337
208337
  LocalStorage::FinalizeAppend(state);
208338
208338
  }
208339
208339
 
208340
+ OptimisticDataWriter *DataTable::CreateOptimisticWriter(ClientContext &context) {
208341
+ auto &local_storage = LocalStorage::Get(context);
208342
+ return local_storage.CreateOptimisticWriter(this);
208343
+ }
208344
+
208340
208345
  void DataTable::LocalMerge(ClientContext &context, RowGroupCollection &collection) {
208341
208346
  auto &local_storage = LocalStorage::Get(context);
208342
208347
  local_storage.LocalMerge(this, collection);
@@ -209000,7 +209005,7 @@ void OptimisticDataWriter::Rollback() {
209000
209005
  if (!written_blocks.empty()) {
209001
209006
  auto &block_manager = table->info->table_io_manager->GetBlockManagerForRowData();
209002
209007
  for (auto block_id : written_blocks) {
209003
- block_manager.MarkBlockAsModified(block_id);
209008
+ block_manager.MarkBlockAsFree(block_id);
209004
209009
  }
209005
209010
  }
209006
209011
  }
@@ -209034,7 +209039,7 @@ LocalTableStorage::LocalTableStorage(DataTable &new_dt, LocalTableStorage &paren
209034
209039
  const LogicalType &target_type, const vector<column_t> &bound_columns,
209035
209040
  Expression &cast_expr)
209036
209041
  : table(&new_dt), allocator(Allocator::Get(table->db)), deleted_rows(parent.deleted_rows),
209037
- optimistic_writer(table, parent.optimistic_writer) {
209042
+ optimistic_writer(table, parent.optimistic_writer), optimistic_writers(move(parent.optimistic_writers)) {
209038
209043
  row_groups = parent.row_groups->AlterType(changed_idx, target_type, bound_columns, cast_expr);
209039
209044
  parent.row_groups.reset();
209040
209045
  indexes.Move(parent.indexes);
@@ -209042,7 +209047,7 @@ LocalTableStorage::LocalTableStorage(DataTable &new_dt, LocalTableStorage &paren
209042
209047
 
209043
209048
  LocalTableStorage::LocalTableStorage(DataTable &new_dt, LocalTableStorage &parent, idx_t drop_idx)
209044
209049
  : table(&new_dt), allocator(Allocator::Get(table->db)), deleted_rows(parent.deleted_rows),
209045
- optimistic_writer(table, parent.optimistic_writer) {
209050
+ optimistic_writer(table, parent.optimistic_writer), optimistic_writers(move(parent.optimistic_writers)) {
209046
209051
  row_groups = parent.row_groups->RemoveColumn(drop_idx);
209047
209052
  parent.row_groups.reset();
209048
209053
  indexes.Move(parent.indexes);
@@ -209051,7 +209056,7 @@ LocalTableStorage::LocalTableStorage(DataTable &new_dt, LocalTableStorage &paren
209051
209056
  LocalTableStorage::LocalTableStorage(DataTable &new_dt, LocalTableStorage &parent, ColumnDefinition &new_column,
209052
209057
  Expression *default_value)
209053
209058
  : table(&new_dt), allocator(Allocator::Get(table->db)), deleted_rows(parent.deleted_rows),
209054
- optimistic_writer(table, parent.optimistic_writer) {
209059
+ optimistic_writer(table, parent.optimistic_writer), optimistic_writers(move(parent.optimistic_writers)) {
209055
209060
  row_groups = parent.row_groups->AddColumn(new_column, default_value);
209056
209061
  parent.row_groups.reset();
209057
209062
  indexes.Move(parent.indexes);
@@ -209094,6 +209099,33 @@ void LocalTableStorage::FlushToDisk() {
209094
209099
  optimistic_writer.FinalFlush();
209095
209100
  }
209096
209101
 
209102
+ bool LocalTableStorage::AppendToIndexes(Transaction &transaction, RowGroupCollection &source,
209103
+ TableIndexList &index_list, const vector<LogicalType> &table_types,
209104
+ row_t &start_row) {
209105
+ // only need to scan for index append
209106
+ // figure out which columns we need to scan for the set of indexes
209107
+ auto columns = index_list.GetRequiredColumns();
209108
+ // create an empty mock chunk that contains all the correct types for the table
209109
+ DataChunk mock_chunk;
209110
+ mock_chunk.InitializeEmpty(table_types);
209111
+ bool success = true;
209112
+ source.Scan(transaction, columns, [&](DataChunk &chunk) -> bool {
209113
+ // construct the mock chunk by referencing the required columns
209114
+ for (idx_t i = 0; i < columns.size(); i++) {
209115
+ mock_chunk.data[columns[i]].Reference(chunk.data[i]);
209116
+ }
209117
+ mock_chunk.SetCardinality(chunk);
209118
+ // append this chunk to the indexes of the table
209119
+ if (!DataTable::AppendToIndexes(index_list, mock_chunk, start_row)) {
209120
+ success = false;
209121
+ return false;
209122
+ }
209123
+ start_row += chunk.size();
209124
+ return true;
209125
+ });
209126
+ return success;
209127
+ }
209128
+
209097
209129
  void LocalTableStorage::AppendToIndexes(Transaction &transaction, TableAppendState &append_state, idx_t append_count,
209098
209130
  bool append_to_table) {
209099
209131
  bool constraint_violated = false;
@@ -209113,26 +209145,8 @@ void LocalTableStorage::AppendToIndexes(Transaction &transaction, TableAppendSta
209113
209145
  return true;
209114
209146
  });
209115
209147
  } else {
209116
- // only need to scan for index append
209117
- // figure out which columns we need to scan for the set of indexes
209118
- auto columns = table->info->indexes.GetRequiredColumns();
209119
- // create an empty mock chunk that contains all the correct types for the table
209120
- DataChunk mock_chunk;
209121
- mock_chunk.InitializeEmpty(table->GetTypes());
209122
- row_groups->Scan(transaction, columns, [&](DataChunk &chunk) -> bool {
209123
- // construct the mock chunk by referencing the required columns
209124
- for (idx_t i = 0; i < columns.size(); i++) {
209125
- mock_chunk.data[columns[i]].Reference(chunk.data[i]);
209126
- }
209127
- mock_chunk.SetCardinality(chunk);
209128
- // append this chunk to the indexes of the table
209129
- if (!table->AppendToIndexes(mock_chunk, append_state.current_row)) {
209130
- constraint_violated = true;
209131
- return false;
209132
- }
209133
- append_state.current_row += chunk.size();
209134
- return true;
209135
- });
209148
+ constraint_violated = !AppendToIndexes(transaction, *row_groups, table->info->indexes, table->GetTypes(),
209149
+ append_state.current_row);
209136
209150
  }
209137
209151
  if (constraint_violated) {
209138
209152
  // need to revert the append
@@ -209156,8 +209170,18 @@ void LocalTableStorage::AppendToIndexes(Transaction &transaction, TableAppendSta
209156
209170
  }
209157
209171
  }
209158
209172
 
209173
+ OptimisticDataWriter *LocalTableStorage::CreateOptimisticWriter() {
209174
+ auto writer = make_unique<OptimisticDataWriter>(table);
209175
+ optimistic_writers.push_back(move(writer));
209176
+ return optimistic_writers.back().get();
209177
+ }
209178
+
209159
209179
  void LocalTableStorage::Rollback() {
209160
209180
  optimistic_writer.Rollback();
209181
+ for (auto &writer : optimistic_writers) {
209182
+ writer->Rollback();
209183
+ }
209184
+ optimistic_writers.clear();
209161
209185
  }
209162
209186
 
209163
209187
  //===--------------------------------------------------------------------===//
@@ -209292,9 +209316,22 @@ void LocalStorage::FinalizeAppend(LocalAppendState &state) {
209292
209316
 
209293
209317
  void LocalStorage::LocalMerge(DataTable *table, RowGroupCollection &collection) {
209294
209318
  auto storage = table_manager.GetOrCreateStorage(table);
209319
+ if (!storage->indexes.Empty()) {
209320
+ // append data to indexes if required
209321
+ row_t base_id = MAX_ROW_ID + storage->row_groups->GetTotalRows();
209322
+ bool success = storage->AppendToIndexes(transaction, collection, storage->indexes, table->GetTypes(), base_id);
209323
+ if (!success) {
209324
+ throw ConstraintException("PRIMARY KEY or UNIQUE constraint violated: duplicated key");
209325
+ }
209326
+ }
209295
209327
  storage->row_groups->MergeStorage(collection);
209296
209328
  }
209297
209329
 
209330
+ OptimisticDataWriter *LocalStorage::CreateOptimisticWriter(DataTable *table) {
209331
+ auto storage = table_manager.GetOrCreateStorage(table);
209332
+ return storage->CreateOptimisticWriter();
209333
+ }
209334
+
209298
209335
  bool LocalStorage::ChangesMade() noexcept {
209299
209336
  return !table_manager.IsEmpty();
209300
209337
  }
@@ -209737,7 +209774,9 @@ public:
209737
209774
  block_id_t GetFreeBlockId() override;
209738
209775
  //! Returns whether or not a specified block is the root block
209739
209776
  bool IsRootBlock(block_id_t root) override;
209740
- //! Mark a block as modified
209777
+ //! Mark a block as free (immediately re-writeable)
209778
+ void MarkBlockAsFree(block_id_t block_id) override;
209779
+ //! Mark a block as modified (re-writeable after a checkpoint)
209741
209780
  void MarkBlockAsModified(block_id_t block_id) override;
209742
209781
  //! Increase the reference count of a block. The block should hold at least one reference
209743
209782
  void IncreaseBlockReferenceCount(block_id_t block_id) override;
@@ -210035,6 +210074,14 @@ block_id_t SingleFileBlockManager::GetFreeBlockId() {
210035
210074
  return block;
210036
210075
  }
210037
210076
 
210077
+ void SingleFileBlockManager::MarkBlockAsFree(block_id_t block_id) {
210078
+ lock_guard<mutex> lock(block_lock);
210079
+ D_ASSERT(block_id >= 0);
210080
+ D_ASSERT(free_list.find(block_id) == free_list.end());
210081
+ multi_use_blocks.erase(block_id);
210082
+ free_list.insert(block_id);
210083
+ }
210084
+
210038
210085
  void SingleFileBlockManager::MarkBlockAsModified(block_id_t block_id) {
210039
210086
  lock_guard<mutex> lock(block_lock);
210040
210087
  D_ASSERT(block_id >= 0);
package/src/duckdb.hpp CHANGED
@@ -11,8 +11,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
11
11
  #pragma once
12
12
  #define DUCKDB_AMALGAMATION 1
13
13
  #define DUCKDB_AMALGAMATION_EXTENDED 1
14
- #define DUCKDB_SOURCE_ID "42003b707e"
15
- #define DUCKDB_VERSION "v0.5.2-dev1460"
14
+ #define DUCKDB_SOURCE_ID "4f495e8eea"
15
+ #define DUCKDB_VERSION "v0.5.2-dev1468"
16
16
  //===----------------------------------------------------------------------===//
17
17
  // DuckDB
18
18
  //
@@ -25197,6 +25197,8 @@ public:
25197
25197
  virtual block_id_t GetFreeBlockId() = 0;
25198
25198
  //! Returns whether or not a specified block is the root block
25199
25199
  virtual bool IsRootBlock(block_id_t root) = 0;
25200
+ //! Mark a block as "free"; free blocks are immediately added to the free list and can be immediately overwritten
25201
+ virtual void MarkBlockAsFree(block_id_t block_id) = 0;
25200
25202
  //! Mark a block as "modified"; modified blocks are added to the free list after a checkpoint (i.e. their data is
25201
25203
  //! assumed to be rewritten)
25202
25204
  virtual void MarkBlockAsModified(block_id_t block_id) = 0;
@@ -26478,8 +26480,10 @@ public:
26478
26480
  TableIndexList indexes;
26479
26481
  //! The number of deleted rows
26480
26482
  idx_t deleted_rows;
26481
- //! The optimistic data writer
26483
+ //! The main optimistic data writer
26482
26484
  OptimisticDataWriter optimistic_writer;
26485
+ //! The set of all optimistic data writers associated with this table
26486
+ vector<unique_ptr<OptimisticDataWriter>> optimistic_writers;
26483
26487
 
26484
26488
  public:
26485
26489
  void InitializeScan(CollectionScanState &state, TableFilterSet *table_filters = nullptr);
@@ -26492,6 +26496,11 @@ public:
26492
26496
 
26493
26497
  void AppendToIndexes(Transaction &transaction, TableAppendState &append_state, idx_t append_count,
26494
26498
  bool append_to_table);
26499
+ bool AppendToIndexes(Transaction &transaction, RowGroupCollection &source, TableIndexList &index_list,
26500
+ const vector<LogicalType> &table_types, row_t &start_row);
26501
+
26502
+ //! Creates an optimistic writer for this table
26503
+ OptimisticDataWriter *CreateOptimisticWriter();
26495
26504
  };
26496
26505
 
26497
26506
  class LocalTableManager {
@@ -26543,6 +26552,8 @@ public:
26543
26552
  static void FinalizeAppend(LocalAppendState &state);
26544
26553
  //! Merge a row group collection into the transaction-local storage
26545
26554
  void LocalMerge(DataTable *table, RowGroupCollection &collection);
26555
+ //! Create an optimistic writer for the specified table
26556
+ OptimisticDataWriter *CreateOptimisticWriter(DataTable *table);
26546
26557
 
26547
26558
  //! Delete a set of rows from the local storage
26548
26559
  idx_t Delete(DataTable *table, Vector &row_ids, idx_t count);
@@ -26631,6 +26642,7 @@ class ClientContext;
26631
26642
  class ColumnDataCollection;
26632
26643
  class ColumnDefinition;
26633
26644
  class DataTable;
26645
+ class OptimisticDataWriter;
26634
26646
  class RowGroup;
26635
26647
  class StorageManager;
26636
26648
  class TableCatalogEntry;
@@ -26699,6 +26711,8 @@ public:
26699
26711
  void LocalAppend(TableCatalogEntry &table, ClientContext &context, ColumnDataCollection &collection);
26700
26712
  //! Merge a row group collection into the transaction-local storage
26701
26713
  void LocalMerge(ClientContext &context, RowGroupCollection &collection);
26714
+ //! Creates an optimistic writer for this table - used for optimistically writing parallel appends
26715
+ OptimisticDataWriter *CreateOptimisticWriter(ClientContext &context);
26702
26716
 
26703
26717
  //! Delete the entries with the specified row identifier from the table
26704
26718
  idx_t Delete(TableCatalogEntry &table, ClientContext &context, Vector &row_ids, idx_t count);