duckdb 0.3.2-dev816.0 → 0.3.2-dev843.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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
- "version": "0.3.2-dev816.0",
4
+ "version": "0.3.2-dev843.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -21139,12 +21139,14 @@ public:
21139
21139
 
21140
21140
  int64_t GetFileSize(FileHandle &handle) override;
21141
21141
 
21142
+ void Reset(FileHandle &handle) override;
21142
21143
  bool OnDiskFile(FileHandle &handle) override {
21143
21144
  return false;
21144
21145
  };
21145
21146
  bool CanSeek() override {
21146
21147
  return false;
21147
21148
  }
21149
+ void FileSync(FileHandle &handle) override;
21148
21150
 
21149
21151
  std::string GetName() const override {
21150
21152
  return "PipeFileSystem";
@@ -21181,6 +21183,10 @@ int64_t PipeFile::WriteChunk(void *buffer, int64_t nr_bytes) {
21181
21183
  return child_handle->Write(buffer, nr_bytes);
21182
21184
  }
21183
21185
 
21186
+ void PipeFileSystem::Reset(FileHandle &handle) {
21187
+ throw InternalException("Cannot reset pipe file system");
21188
+ }
21189
+
21184
21190
  int64_t PipeFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes) {
21185
21191
  auto &pipe = (PipeFile &)handle;
21186
21192
  return pipe.ReadChunk(buffer, nr_bytes);
@@ -21195,6 +21201,9 @@ int64_t PipeFileSystem::GetFileSize(FileHandle &handle) {
21195
21201
  return 0;
21196
21202
  }
21197
21203
 
21204
+ void PipeFileSystem::FileSync(FileHandle &handle) {
21205
+ }
21206
+
21198
21207
  unique_ptr<FileHandle> PipeFileSystem::OpenPipe(unique_ptr<FileHandle> handle) {
21199
21208
  auto path = handle->path;
21200
21209
  return make_unique<PipeFile>(move(handle), path);
@@ -56617,6 +56626,125 @@ string PhysicalTopN::ParamsToString() const {
56617
56626
 
56618
56627
  namespace duckdb {
56619
56628
 
56629
+ struct CSVFileHandle {
56630
+ public:
56631
+ explicit CSVFileHandle(unique_ptr<FileHandle> file_handle_p) : file_handle(move(file_handle_p)) {
56632
+ can_seek = file_handle->CanSeek();
56633
+ plain_file_source = file_handle->OnDiskFile() && can_seek;
56634
+ file_size = file_handle->GetFileSize();
56635
+ }
56636
+
56637
+ bool CanSeek() {
56638
+ return can_seek;
56639
+ }
56640
+ void Seek(idx_t position) {
56641
+ if (!can_seek) {
56642
+ throw InternalException("Cannot seek in this file");
56643
+ }
56644
+ file_handle->Seek(position);
56645
+ }
56646
+ idx_t SeekPosition() {
56647
+ if (!can_seek) {
56648
+ throw InternalException("Cannot seek in this file");
56649
+ }
56650
+ return file_handle->SeekPosition();
56651
+ }
56652
+ void Reset() {
56653
+ if (plain_file_source) {
56654
+ file_handle->Reset();
56655
+ } else {
56656
+ if (!reset_enabled) {
56657
+ throw InternalException("Reset called but reset is not enabled for this CSV Handle");
56658
+ }
56659
+ read_position = 0;
56660
+ }
56661
+ }
56662
+ bool PlainFileSource() {
56663
+ return plain_file_source;
56664
+ }
56665
+
56666
+ idx_t FileSize() {
56667
+ return file_size;
56668
+ }
56669
+
56670
+ idx_t Read(void *buffer, idx_t nr_bytes) {
56671
+ if (!plain_file_source) {
56672
+ // not a plain file source: we need to do some bookkeeping around the reset functionality
56673
+ idx_t result_offset = 0;
56674
+ if (read_position < buffer_size) {
56675
+ // we need to read from our cached buffer
56676
+ auto buffer_read_count = MinValue<idx_t>(nr_bytes, buffer_size - read_position);
56677
+ memcpy(buffer, cached_buffer.get() + read_position, buffer_read_count);
56678
+ result_offset += buffer_read_count;
56679
+ read_position += buffer_read_count;
56680
+ if (result_offset == nr_bytes) {
56681
+ return nr_bytes;
56682
+ }
56683
+ } else if (!reset_enabled && cached_buffer) {
56684
+ // reset is disabled but we still have cached data
56685
+ // we can remove any cached data
56686
+ cached_buffer.reset();
56687
+ buffer_size = 0;
56688
+ buffer_capacity = 0;
56689
+ read_position = 0;
56690
+ }
56691
+ // we have data left to read from the file
56692
+ // read directly into the buffer
56693
+ auto bytes_read = file_handle->Read((char *)buffer + result_offset, nr_bytes - result_offset);
56694
+ read_position += bytes_read;
56695
+ if (reset_enabled) {
56696
+ // if reset caching is enabled, we need to cache the bytes that we have read
56697
+ if (buffer_size + bytes_read >= buffer_capacity) {
56698
+ // no space; first enlarge the buffer
56699
+ buffer_capacity = MaxValue<idx_t>(NextPowerOfTwo(buffer_size + bytes_read), buffer_capacity * 2);
56700
+
56701
+ auto new_buffer = unique_ptr<data_t[]>(new data_t[buffer_capacity]);
56702
+ if (buffer_size > 0) {
56703
+ memcpy(new_buffer.get(), cached_buffer.get(), buffer_size);
56704
+ }
56705
+ cached_buffer = move(new_buffer);
56706
+ }
56707
+ memcpy(cached_buffer.get() + buffer_size, (char *)buffer + result_offset, bytes_read);
56708
+ buffer_size += bytes_read;
56709
+ }
56710
+
56711
+ return result_offset + bytes_read;
56712
+ } else {
56713
+ return file_handle->Read(buffer, nr_bytes);
56714
+ }
56715
+ }
56716
+
56717
+ string ReadLine() {
56718
+ string result;
56719
+ char buffer[1];
56720
+ while (true) {
56721
+ idx_t tuples_read = Read(buffer, 1);
56722
+ if (tuples_read == 0 || buffer[0] == '\n') {
56723
+ return result;
56724
+ }
56725
+ if (buffer[0] != '\r') {
56726
+ result += buffer[0];
56727
+ }
56728
+ }
56729
+ }
56730
+
56731
+ void DisableReset() {
56732
+ this->reset_enabled = false;
56733
+ }
56734
+
56735
+ private:
56736
+ unique_ptr<FileHandle> file_handle;
56737
+ bool reset_enabled = true;
56738
+ bool can_seek = false;
56739
+ bool plain_file_source = false;
56740
+ idx_t file_size = 0;
56741
+ // reset support
56742
+ unique_ptr<data_t[]> cached_buffer;
56743
+ idx_t read_position = 0;
56744
+ idx_t buffer_size = 0;
56745
+ idx_t buffer_capacity = 0;
56746
+ };
56747
+
56620
56748
  void BufferedCSVReaderOptions::SetDelimiter(const string &input) {
56621
56749
  this->delimiter = StringUtil::Replace(input, "\\t", "\t");
56622
56750
  this->has_delimiter = true;
@@ -56749,6 +56877,13 @@ BufferedCSVReader::BufferedCSVReader(ClientContext &context, BufferedCSVReaderOp
56749
56877
  requested_types) {
56750
56878
  }
56751
56879
 
56880
+ BufferedCSVReader::~BufferedCSVReader() {
56881
+ }
56882
+
56883
+ idx_t BufferedCSVReader::GetFileSize() {
56884
+ return file_handle ? file_handle->FileSize() : 0;
56885
+ }
56886
+
56752
56887
  void BufferedCSVReader::Initialize(const vector<LogicalType> &requested_types) {
56753
56888
  PrepareComplexParser();
56754
56889
  if (options.auto_detect) {
@@ -56765,6 +56900,9 @@ void BufferedCSVReader::Initialize(const vector<LogicalType> &requested_types) {
56765
56900
  SkipRowsAndReadHeader(options.skip_rows, options.header);
56766
56901
  }
56767
56902
  InitParseChunk(sql_types.size());
56903
+ // we only need reset support during the automatic CSV type detection
56904
+ // since reset support might require caching (in the case of streams), we disable it for the remainder
56905
+ file_handle->DisableReset();
56768
56906
  }
56769
56907
 
56770
56908
  void BufferedCSVReader::PrepareComplexParser() {
@@ -56773,12 +56911,10 @@ void BufferedCSVReader::PrepareComplexParser() {
56773
56911
  quote_search = TextSearchShiftArray(options.quote);
56774
56912
  }
56775
56913
 
56776
- unique_ptr<FileHandle> BufferedCSVReader::OpenCSV(const BufferedCSVReaderOptions &options) {
56777
- auto result = fs.OpenFile(options.file_path.c_str(), FileFlags::FILE_FLAGS_READ, FileLockType::NO_LOCK,
56778
- options.compression, this->opener);
56779
- plain_file_source = result->OnDiskFile() && result->CanSeek();
56780
- file_size = result->GetFileSize();
56781
- return result;
56914
+ unique_ptr<CSVFileHandle> BufferedCSVReader::OpenCSV(const BufferedCSVReaderOptions &options) {
56915
+ auto file_handle = fs.OpenFile(options.file_path.c_str(), FileFlags::FILE_FLAGS_READ, FileLockType::NO_LOCK,
56916
+ options.compression, this->opener);
56917
+ return make_unique<CSVFileHandle>(move(file_handle));
56782
56918
  }
56783
56919
 
56784
56920
  // Helper function to generate column names
@@ -56944,7 +57080,7 @@ bool BufferedCSVReader::JumpToNextSample() {
56944
57080
  // assess if it makes sense to jump, based on size of the first chunk relative to size of the entire file
56945
57081
  if (sample_chunk_idx == 0) {
56946
57082
  idx_t bytes_first_chunk = bytes_in_chunk;
56947
- double chunks_fit = (file_size / (double)bytes_first_chunk);
57083
+ double chunks_fit = (file_handle->FileSize() / (double)bytes_first_chunk);
56948
57084
  jumping_samples = chunks_fit >= options.sample_chunks;
56949
57085
 
56950
57086
  // jump back to the beginning
@@ -56959,7 +57095,7 @@ bool BufferedCSVReader::JumpToNextSample() {
56959
57095
 
56960
57096
  // if we deal with any other sources than plaintext files, jumping_samples can be tricky. In that case
56961
57097
  // we just read x continuous chunks from the stream TODO: make jumps possible for zipfiles.
56962
- if (!plain_file_source || !jumping_samples) {
57098
+ if (!file_handle->PlainFileSource() || !jumping_samples) {
56963
57099
  sample_chunk_idx++;
56964
57100
  return true;
56965
57101
  }
@@ -56969,13 +57105,13 @@ bool BufferedCSVReader::JumpToNextSample() {
56969
57105
  bytes_per_line_avg = ((bytes_per_line_avg * (sample_chunk_idx)) + bytes_per_line) / (sample_chunk_idx + 1);
56970
57106
 
56971
57107
  // if none of the previous conditions were met, we can jump
56972
- idx_t partition_size = (idx_t)round(file_size / (double)options.sample_chunks);
57108
+ idx_t partition_size = (idx_t)round(file_handle->FileSize() / (double)options.sample_chunks);
56973
57109
 
56974
57110
  // calculate offset to end of the current partition
56975
57111
  int64_t offset = partition_size - bytes_in_chunk - remaining_bytes_in_buffer;
56976
57112
  auto current_pos = file_handle->SeekPosition();
56977
57113
 
56978
- if (current_pos + offset < file_size) {
57114
+ if (current_pos + offset < file_handle->FileSize()) {
56979
57115
  // set position in stream and clear failure bits
56980
57116
  file_handle->Seek(current_pos + offset);
56981
57117
 
@@ -56986,10 +57122,10 @@ bool BufferedCSVReader::JumpToNextSample() {
56986
57122
  // seek backwards from the end in last chunk and hope to catch the end of the file
56987
57123
  // TODO: actually it would be good to make sure that the end of file is being reached, because
56988
57124
  // messy end-lines are quite common. For this case, however, we first need a skip_end detection anyways.
56989
- file_handle->Seek(file_size - bytes_in_chunk);
57125
+ file_handle->Seek(file_handle->FileSize() - bytes_in_chunk);
56990
57126
 
56991
57127
  // estimate linenr
56992
- linenr = (idx_t)round((file_size - bytes_in_chunk) / bytes_per_line_avg);
57128
+ linenr = (idx_t)round((file_handle->FileSize() - bytes_in_chunk) / bytes_per_line_avg);
56993
57129
  linenr_estimated = true;
56994
57130
  }
56995
57131
 
@@ -57143,6 +57279,7 @@ void BufferedCSVReader::DetectDialect(const vector<LogicalType> &requested_types
57143
57279
 
57144
57280
  JumpToBeginning(original_options.skip_rows);
57145
57281
  sniffed_column_counts.clear();
57282
+
57146
57283
  if (!TryParseCSV(ParserMode::SNIFFING_DIALECT)) {
57147
57284
  continue;
57148
57285
  }
@@ -88587,9 +88724,9 @@ static void GenerateUUIDFunction(DataChunk &args, ExpressionState &state, Vector
88587
88724
  }
88588
88725
 
88589
88726
  void UUIDFun::RegisterFunction(BuiltinFunctions &set) {
88727
+ ScalarFunction uuid_function({}, LogicalType::UUID, GenerateUUIDFunction, true, UUIDRandomBind);
88590
88728
  // generate a random uuid
88591
- set.AddFunction(
88592
- ScalarFunction("gen_random_uuid", {}, LogicalType::UUID, GenerateUUIDFunction, true, UUIDRandomBind));
88729
+ set.AddFunction({"uuid", "gen_random_uuid"}, uuid_function);
88593
88730
  }
88594
88731
 
88595
88732
  } // namespace duckdb
@@ -91542,7 +91679,7 @@ static unique_ptr<FunctionOperatorData> ReadCSVInit(ClientContext &context, cons
91542
91679
  result->csv_reader = make_unique<BufferedCSVReader>(context, bind_data.options, bind_data.sql_types);
91543
91680
  }
91544
91681
  bind_data.bytes_read = 0;
91545
- bind_data.file_size = result->csv_reader->file_size;
91682
+ bind_data.file_size = result->csv_reader->GetFileSize();
91546
91683
  result->file_index = 1;
91547
91684
  return move(result);
91548
91685
  }
@@ -98287,8 +98424,8 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
98287
98424
  } catch (std::exception &ex) {
98288
98425
  original_result->error = ex.what();
98289
98426
  original_result->success = false;
98290
- interrupted = false;
98291
98427
  }
98428
+ interrupted = false;
98292
98429
 
98293
98430
  // check explain, only if q does not already contain EXPLAIN
98294
98431
  if (original_result->success) {
@@ -98308,8 +98445,8 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
98308
98445
  } catch (std::exception &ex) {
98309
98446
  copied_result->error = ex.what();
98310
98447
  copied_result->success = false;
98311
- interrupted = false;
98312
98448
  }
98449
+ interrupted = false;
98313
98450
  // now execute the deserialized statement
98314
98451
  try {
98315
98452
  auto result = RunStatementInternal(lock, query, move(deserialized_stmt), false, false);
@@ -98317,8 +98454,8 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
98317
98454
  } catch (std::exception &ex) {
98318
98455
  deserialized_result->error = ex.what();
98319
98456
  deserialized_result->success = false;
98320
- interrupted = false;
98321
98457
  }
98458
+ interrupted = false;
98322
98459
  // now execute the unoptimized statement
98323
98460
  config.enable_optimizer = false;
98324
98461
  try {
@@ -98327,8 +98464,8 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
98327
98464
  } catch (std::exception &ex) {
98328
98465
  unoptimized_result->error = ex.what();
98329
98466
  unoptimized_result->success = false;
98330
- interrupted = false;
98331
98467
  }
98468
+ interrupted = false;
98332
98469
  config.enable_optimizer = true;
98333
98470
 
98334
98471
  if (profiling_is_enabled) {
@@ -119251,6 +119388,10 @@ FilterPropagateResult StatisticsPropagator::PropagateComparison(BaseStatistics &
119251
119388
  // only handle numerics for now
119252
119389
  switch (left.type.InternalType()) {
119253
119390
  case PhysicalType::BOOL:
119391
+ case PhysicalType::UINT8:
119392
+ case PhysicalType::UINT16:
119393
+ case PhysicalType::UINT32:
119394
+ case PhysicalType::UINT64:
119254
119395
  case PhysicalType::INT8:
119255
119396
  case PhysicalType::INT16:
119256
119397
  case PhysicalType::INT32:
@@ -119378,6 +119519,10 @@ namespace duckdb {
119378
119519
  unique_ptr<BaseStatistics> StatisticsPropagator::StatisticsFromValue(const Value &input) {
119379
119520
  switch (input.type().InternalType()) {
119380
119521
  case PhysicalType::BOOL:
119522
+ case PhysicalType::UINT8:
119523
+ case PhysicalType::UINT16:
119524
+ case PhysicalType::UINT32:
119525
+ case PhysicalType::UINT64:
119381
119526
  case PhysicalType::INT8:
119382
119527
  case PhysicalType::INT16:
119383
119528
  case PhysicalType::INT32:
@@ -160562,7 +160707,6 @@ unique_ptr<BaseStatistics> StringStatistics::Copy() {
160562
160707
  memcpy(stats->max, max, MAX_STRING_MINMAX_SIZE);
160563
160708
  stats->has_unicode = has_unicode;
160564
160709
  stats->max_string_length = max_string_length;
160565
- stats->max_string_length = max_string_length;
160566
160710
  if (validity_stats) {
160567
160711
  stats->validity_stats = validity_stats->Copy();
160568
160712
  }
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 "684aaf4e7"
15
- #define DUCKDB_VERSION "0.3.2-dev816"
14
+ #define DUCKDB_SOURCE_ID "dbe8a9905"
15
+ #define DUCKDB_VERSION "0.3.2-dev843"
16
16
  //===----------------------------------------------------------------------===//
17
17
  // DuckDB
18
18
  //
@@ -20341,6 +20341,7 @@ protected:
20341
20341
 
20342
20342
  namespace duckdb {
20343
20343
  struct CopyInfo;
20344
+ struct CSVFileHandle;
20344
20345
  struct FileHandle;
20345
20346
  struct StrpTimeFormat;
20346
20347
 
@@ -20441,15 +20442,14 @@ public:
20441
20442
 
20442
20443
  BufferedCSVReader(FileSystem &fs, FileOpener *opener, BufferedCSVReaderOptions options,
20443
20444
  const vector<LogicalType> &requested_types = vector<LogicalType>());
20445
+ ~BufferedCSVReader();
20444
20446
 
20445
20447
  FileSystem &fs;
20446
20448
  FileOpener *opener;
20447
20449
  BufferedCSVReaderOptions options;
20448
20450
  vector<LogicalType> sql_types;
20449
20451
  vector<string> col_names;
20450
- unique_ptr<FileHandle> file_handle;
20451
- bool plain_file_source = false;
20452
- idx_t file_size = 0;
20452
+ unique_ptr<CSVFileHandle> file_handle;
20453
20453
 
20454
20454
  unique_ptr<char[]> buffer;
20455
20455
  idx_t buffer_size;
@@ -20481,6 +20481,8 @@ public:
20481
20481
  //! Extract a single DataChunk from the CSV file and stores it in insert_chunk
20482
20482
  void ParseCSV(DataChunk &insert_chunk);
20483
20483
 
20484
+ idx_t GetFileSize();
20485
+
20484
20486
  private:
20485
20487
  //! Initialize Parser
20486
20488
  void Initialize(const vector<LogicalType> &requested_types);
@@ -20527,7 +20529,7 @@ private:
20527
20529
  //! Reads a new buffer from the CSV file if the current one has been exhausted
20528
20530
  bool ReadBuffer(idx_t &start);
20529
20531
 
20530
- unique_ptr<FileHandle> OpenCSV(const BufferedCSVReaderOptions &options);
20532
+ unique_ptr<CSVFileHandle> OpenCSV(const BufferedCSVReaderOptions &options);
20531
20533
 
20532
20534
  //! First phase of auto detection: detect CSV dialect (i.e. delimiter, quote rules, etc)
20533
20535
  void DetectDialect(const vector<LogicalType> &requested_types, BufferedCSVReaderOptions &original_options,