duckdb 0.2.10-dev325.0 → 0.2.10-dev337.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.2.10-dev325.0",
4
+ "version": "0.2.10-dev337.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -18182,6 +18182,10 @@ FileSystem &FileSystem::GetFileSystem(ClientContext &context) {
18182
18182
  return *context.db->config.file_system;
18183
18183
  }
18184
18184
 
18185
+ FileOpener *FileSystem::GetFileOpener(ClientContext &context) {
18186
+ return context.file_opener.get();
18187
+ }
18188
+
18185
18189
  #ifndef _WIN32
18186
18190
  string FileSystem::PathSeparator() {
18187
18191
  return "/";
@@ -18283,7 +18287,7 @@ string FileSystem::GetHomeDirectory() {
18283
18287
 
18284
18288
  // LCOV_EXCL_START
18285
18289
  unique_ptr<FileHandle> FileSystem::OpenFile(const string &path, uint8_t flags, FileLockType lock,
18286
- FileCompressionType compression) {
18290
+ FileCompressionType compression, FileOpener *opener) {
18287
18291
  throw NotImplementedException("%s: OpenFile is not implemented!", GetName());
18288
18292
  }
18289
18293
 
@@ -20215,7 +20219,8 @@ namespace duckdb {
20215
20219
  class LocalFileSystem : public FileSystem {
20216
20220
  public:
20217
20221
  unique_ptr<FileHandle> OpenFile(const string &path, uint8_t flags, FileLockType lock = FileLockType::NO_LOCK,
20218
- FileCompressionType compression = FileCompressionType::UNCOMPRESSED) override;
20222
+ FileCompressionType compression = FileCompressionType::UNCOMPRESSED,
20223
+ FileOpener *opener = nullptr) override;
20219
20224
 
20220
20225
  //! Read exactly nr_bytes from the specified location in the file. Fails if nr_bytes could not be read. This is
20221
20226
  //! equivalent to calling SetFilePointer(location) followed by calling Read().
@@ -20322,14 +20327,18 @@ extern "C" WINBASEAPI BOOL WINAPI GetPhysicallyInstalledSystemMemory(PULONGLONG)
20322
20327
  namespace duckdb {
20323
20328
 
20324
20329
  static void AssertValidFileFlags(uint8_t flags) {
20325
- // cannot combine Read and Write flags
20326
- D_ASSERT(!(flags & FileFlags::FILE_FLAGS_READ && flags & FileFlags::FILE_FLAGS_WRITE));
20327
- // cannot combine Read and CREATE/Append flags
20328
- D_ASSERT(!(flags & FileFlags::FILE_FLAGS_READ && flags & FileFlags::FILE_FLAGS_APPEND));
20329
- D_ASSERT(!(flags & FileFlags::FILE_FLAGS_READ && flags & FileFlags::FILE_FLAGS_FILE_CREATE));
20330
- D_ASSERT(!(flags & FileFlags::FILE_FLAGS_READ && flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW));
20330
+ #ifdef DEBUG
20331
+ bool is_read = flags & FileFlags::FILE_FLAGS_READ;
20332
+ bool is_write = flags & FileFlags::FILE_FLAGS_WRITE;
20333
+ // require either READ or WRITE (or both)
20334
+ D_ASSERT(is_read || is_write);
20335
+ // CREATE/Append flags require writing
20336
+ D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_APPEND));
20337
+ D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_FILE_CREATE));
20338
+ D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW));
20331
20339
  // cannot combine CREATE and CREATE_NEW flags
20332
20340
  D_ASSERT(!(flags & FileFlags::FILE_FLAGS_FILE_CREATE && flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW));
20341
+ #endif
20333
20342
  }
20334
20343
 
20335
20344
  #ifndef _WIN32
@@ -20362,8 +20371,33 @@ public:
20362
20371
  int fd;
20363
20372
  };
20364
20373
 
20374
+ static FileType GetFileTypeInternal(int fd) {
20375
+ struct stat s;
20376
+ if (fstat(fd, &s) == -1) {
20377
+ return FileType::FILE_TYPE_INVALID;
20378
+ }
20379
+ switch (s.st_mode & S_IFMT) {
20380
+ case S_IFBLK:
20381
+ return FileType::FILE_TYPE_BLOCKDEV;
20382
+ case S_IFCHR:
20383
+ return FileType::FILE_TYPE_CHARDEV;
20384
+ case S_IFIFO:
20385
+ return FileType::FILE_TYPE_FIFO;
20386
+ case S_IFDIR:
20387
+ return FileType::FILE_TYPE_DIR;
20388
+ case S_IFLNK:
20389
+ return FileType::FILE_TYPE_LINK;
20390
+ case S_IFREG:
20391
+ return FileType::FILE_TYPE_REGULAR;
20392
+ case S_IFSOCK:
20393
+ return FileType::FILE_TYPE_SOCKET;
20394
+ default:
20395
+ return FileType::FILE_TYPE_INVALID;
20396
+ }
20397
+ }
20398
+
20365
20399
  unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path, uint8_t flags, FileLockType lock_type,
20366
- FileCompressionType compression) {
20400
+ FileCompressionType compression, FileOpener *opener) {
20367
20401
  if (compression != FileCompressionType::UNCOMPRESSED) {
20368
20402
  throw NotImplementedException("Unsupported compression type for default file system");
20369
20403
  }
@@ -20372,12 +20406,21 @@ unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path, uint8_t fla
20372
20406
 
20373
20407
  int open_flags = 0;
20374
20408
  int rc;
20375
- if (flags & FileFlags::FILE_FLAGS_READ) {
20409
+ bool open_read = flags & FileFlags::FILE_FLAGS_READ;
20410
+ bool open_write = flags & FileFlags::FILE_FLAGS_WRITE;
20411
+ if (open_read && open_write) {
20412
+ open_flags = O_RDWR;
20413
+ } else if (open_read) {
20376
20414
  open_flags = O_RDONLY;
20415
+ } else if (open_write) {
20416
+ open_flags = O_WRONLY;
20377
20417
  } else {
20418
+ throw InternalException("READ, WRITE or both should be specified when opening a file");
20419
+ }
20420
+ if (open_write) {
20378
20421
  // need Read or Write
20379
20422
  D_ASSERT(flags & FileFlags::FILE_FLAGS_WRITE);
20380
- open_flags = O_RDWR | O_CLOEXEC;
20423
+ open_flags |= O_CLOEXEC;
20381
20424
  if (flags & FileFlags::FILE_FLAGS_FILE_CREATE) {
20382
20425
  open_flags |= O_CREAT;
20383
20426
  } else if (flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW) {
@@ -20413,15 +20456,19 @@ unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path, uint8_t fla
20413
20456
  // #endif
20414
20457
  if (lock_type != FileLockType::NO_LOCK) {
20415
20458
  // set lock on file
20416
- struct flock fl;
20417
- memset(&fl, 0, sizeof fl);
20418
- fl.l_type = lock_type == FileLockType::READ_LOCK ? F_RDLCK : F_WRLCK;
20419
- fl.l_whence = SEEK_SET;
20420
- fl.l_start = 0;
20421
- fl.l_len = 0;
20422
- rc = fcntl(fd, F_SETLK, &fl);
20423
- if (rc == -1) {
20424
- throw IOException("Could not set lock on file \"%s\": %s", path, strerror(errno));
20459
+ // but only if it is not an input/output stream
20460
+ auto file_type = GetFileTypeInternal(fd);
20461
+ if (file_type != FileType::FILE_TYPE_FIFO && file_type != FileType::FILE_TYPE_SOCKET) {
20462
+ struct flock fl;
20463
+ memset(&fl, 0, sizeof fl);
20464
+ fl.l_type = lock_type == FileLockType::READ_LOCK ? F_RDLCK : F_WRLCK;
20465
+ fl.l_whence = SEEK_SET;
20466
+ fl.l_start = 0;
20467
+ fl.l_len = 0;
20468
+ rc = fcntl(fd, F_SETLK, &fl);
20469
+ if (rc == -1) {
20470
+ throw IOException("Could not set lock on file \"%s\": %s", path, strerror(errno));
20471
+ }
20425
20472
  }
20426
20473
  }
20427
20474
  return make_unique<UnixFileHandle>(*this, path, fd);
@@ -20507,28 +20554,7 @@ time_t LocalFileSystem::GetLastModifiedTime(FileHandle &handle) {
20507
20554
 
20508
20555
  FileType LocalFileSystem::GetFileType(FileHandle &handle) {
20509
20556
  int fd = ((UnixFileHandle &)handle).fd;
20510
- struct stat s;
20511
- if (fstat(fd, &s) == -1) {
20512
- return FileType::FILE_TYPE_INVALID;
20513
- }
20514
- switch (s.st_mode & S_IFMT) {
20515
- case S_IFBLK:
20516
- return FileType::FILE_TYPE_BLOCKDEV;
20517
- case S_IFCHR:
20518
- return FileType::FILE_TYPE_CHARDEV;
20519
- case S_IFIFO:
20520
- return FileType::FILE_TYPE_FIFO;
20521
- case S_IFDIR:
20522
- return FileType::FILE_TYPE_DIR;
20523
- case S_IFLNK:
20524
- return FileType::FILE_TYPE_LINK;
20525
- case S_IFREG:
20526
- return FileType::FILE_TYPE_REGULAR;
20527
- case S_IFSOCK:
20528
- return FileType::FILE_TYPE_SOCKET;
20529
- default:
20530
- return FileType::FILE_TYPE_INVALID;
20531
- }
20557
+ return GetFileTypeInternal(fd);
20532
20558
  }
20533
20559
 
20534
20560
  void LocalFileSystem::Truncate(FileHandle &handle, int64_t new_size) {
@@ -20721,7 +20747,7 @@ public:
20721
20747
  };
20722
20748
 
20723
20749
  unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path, uint8_t flags, FileLockType lock_type,
20724
- FileCompressionType compression) {
20750
+ FileCompressionType compression, FileOpener *opener) {
20725
20751
  if (compression != FileCompressionType::UNCOMPRESSED) {
20726
20752
  throw NotImplementedException("Unsupported compression type for default file system");
20727
20753
  }
@@ -20731,14 +20757,21 @@ unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path, uint8_t fla
20731
20757
  DWORD share_mode;
20732
20758
  DWORD creation_disposition = OPEN_EXISTING;
20733
20759
  DWORD flags_and_attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
20734
- if (flags & FileFlags::FILE_FLAGS_READ) {
20760
+ bool open_read = flags & FileFlags::FILE_FLAGS_READ;
20761
+ bool open_write = flags & FileFlags::FILE_FLAGS_WRITE;
20762
+ if (open_read && open_write) {
20763
+ desired_access = GENERIC_READ | GENERIC_WRITE;
20764
+ share_mode = 0;
20765
+ } else if (open_read) {
20735
20766
  desired_access = GENERIC_READ;
20736
20767
  share_mode = FILE_SHARE_READ;
20737
- } else {
20738
- // need Read or Write
20739
- D_ASSERT(flags & FileFlags::FILE_FLAGS_WRITE);
20740
- desired_access = GENERIC_READ | GENERIC_WRITE;
20768
+ } else if (open_write) {
20769
+ desired_access = GENERIC_WRITE;
20741
20770
  share_mode = 0;
20771
+ } else {
20772
+ throw InternalException("READ, WRITE or both should be specified when opening a file");
20773
+ }
20774
+ if (open_write) {
20742
20775
  if (flags & FileFlags::FILE_FLAGS_FILE_CREATE) {
20743
20776
  creation_disposition = OPEN_ALWAYS;
20744
20777
  } else if (flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW) {
@@ -28380,7 +28413,7 @@ namespace duckdb {
28380
28413
 
28381
28414
  class BufferedFileReader : public Deserializer {
28382
28415
  public:
28383
- BufferedFileReader(FileSystem &fs, const char *path);
28416
+ BufferedFileReader(FileSystem &fs, const char *path, FileOpener *opener = nullptr);
28384
28417
 
28385
28418
  FileSystem &fs;
28386
28419
  unique_ptr<data_t[]> data;
@@ -28412,9 +28445,10 @@ private:
28412
28445
 
28413
28446
  namespace duckdb {
28414
28447
 
28415
- BufferedFileReader::BufferedFileReader(FileSystem &fs, const char *path)
28448
+ BufferedFileReader::BufferedFileReader(FileSystem &fs, const char *path, FileOpener *opener)
28416
28449
  : fs(fs), data(unique_ptr<data_t[]>(new data_t[FILE_BUFFER_SIZE])), offset(0), read_data(0), total_read(0) {
28417
- handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_READ, FileLockType::READ_LOCK);
28450
+ handle =
28451
+ fs.OpenFile(path, FileFlags::FILE_FLAGS_READ, FileLockType::READ_LOCK, FileSystem::DEFAULT_COMPRESSION, opener);
28418
28452
  file_size = fs.GetFileSize(*handle);
28419
28453
  }
28420
28454
 
@@ -28467,9 +28501,12 @@ bool BufferedFileReader::Finished() {
28467
28501
 
28468
28502
  namespace duckdb {
28469
28503
 
28470
- BufferedFileWriter::BufferedFileWriter(FileSystem &fs, const string &path, uint8_t open_flags)
28504
+ // Remove this when we switch C++17: https://stackoverflow.com/a/53350948
28505
+ constexpr uint8_t BufferedFileWriter::DEFAULT_OPEN_FLAGS;
28506
+
28507
+ BufferedFileWriter::BufferedFileWriter(FileSystem &fs, const string &path, uint8_t open_flags, FileOpener *opener)
28471
28508
  : fs(fs), data(unique_ptr<data_t[]>(new data_t[FILE_BUFFER_SIZE])), offset(0), total_written(0) {
28472
- handle = fs.OpenFile(path, open_flags, FileLockType::WRITE_LOCK);
28509
+ handle = fs.OpenFile(path, open_flags, FileLockType::WRITE_LOCK, FileSystem::DEFAULT_COMPRESSION, opener);
28473
28510
  }
28474
28511
 
28475
28512
  int64_t BufferedFileWriter::GetFileSize() {
@@ -45310,7 +45347,8 @@ public:
45310
45347
  VirtualFileSystem();
45311
45348
 
45312
45349
  unique_ptr<FileHandle> OpenFile(const string &path, uint8_t flags, FileLockType lock = FileLockType::NO_LOCK,
45313
- FileCompressionType compression = FileCompressionType::UNCOMPRESSED) override;
45350
+ FileCompressionType compression = FileCompressionType::UNCOMPRESSED,
45351
+ FileOpener *opener = nullptr) override;
45314
45352
 
45315
45353
  void Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) override {
45316
45354
  handle.file_system.Read(handle, buffer, nr_bytes, location);
@@ -45414,7 +45452,7 @@ VirtualFileSystem::VirtualFileSystem() : default_fs(FileSystem::CreateLocal()) {
45414
45452
  }
45415
45453
 
45416
45454
  unique_ptr<FileHandle> VirtualFileSystem::OpenFile(const string &path, uint8_t flags, FileLockType lock,
45417
- FileCompressionType compression) {
45455
+ FileCompressionType compression, FileOpener *opener) {
45418
45456
  if (compression == FileCompressionType::AUTO_DETECT) {
45419
45457
  // auto detect compression settings based on file name
45420
45458
  auto lower_path = StringUtil::Lower(path);
@@ -45425,7 +45463,7 @@ unique_ptr<FileHandle> VirtualFileSystem::OpenFile(const string &path, uint8_t f
45425
45463
  }
45426
45464
  }
45427
45465
  // open the base file handle
45428
- auto file_handle = FindFileSystem(path)->OpenFile(path, flags, lock, FileCompressionType::UNCOMPRESSED);
45466
+ auto file_handle = FindFileSystem(path)->OpenFile(path, flags, lock, FileCompressionType::UNCOMPRESSED, opener);
45429
45467
  if (file_handle->GetType() == FileType::FILE_TYPE_FIFO) {
45430
45468
  file_handle = PipeFileSystem::OpenPipe(move(file_handle));
45431
45469
  } else if (compression != FileCompressionType::UNCOMPRESSED) {
@@ -59462,6 +59500,7 @@ struct CopyInfo;
59462
59500
  struct FileHandle;
59463
59501
  struct StrpTimeFormat;
59464
59502
 
59503
+ class FileOpener;
59465
59504
  class FileSystem;
59466
59505
 
59467
59506
  //! The shifts array allows for linear searching of multi-byte values. For each position, it determines the next
@@ -59562,10 +59601,11 @@ public:
59562
59601
  BufferedCSVReader(ClientContext &context, BufferedCSVReaderOptions options,
59563
59602
  const vector<LogicalType> &requested_types = vector<LogicalType>());
59564
59603
 
59565
- BufferedCSVReader(FileSystem &fs, BufferedCSVReaderOptions options,
59604
+ BufferedCSVReader(FileSystem &fs, FileOpener *opener, BufferedCSVReaderOptions options,
59566
59605
  const vector<LogicalType> &requested_types = vector<LogicalType>());
59567
59606
 
59568
59607
  FileSystem &fs;
59608
+ FileOpener *opener;
59569
59609
  BufferedCSVReaderOptions options;
59570
59610
  vector<LogicalType> sql_types;
59571
59611
  vector<string> col_names;
@@ -59798,16 +59838,17 @@ TextSearchShiftArray::TextSearchShiftArray(string search_term) : length(search_t
59798
59838
  }
59799
59839
  }
59800
59840
 
59801
- BufferedCSVReader::BufferedCSVReader(FileSystem &fs_p, BufferedCSVReaderOptions options_p,
59841
+ BufferedCSVReader::BufferedCSVReader(FileSystem &fs_p, FileOpener *opener_p, BufferedCSVReaderOptions options_p,
59802
59842
  const vector<LogicalType> &requested_types)
59803
- : fs(fs_p), options(move(options_p)), buffer_size(0), position(0), start(0) {
59843
+ : fs(fs_p), opener(opener_p), options(move(options_p)), buffer_size(0), position(0), start(0) {
59804
59844
  file_handle = OpenCSV(options);
59805
59845
  Initialize(requested_types);
59806
59846
  }
59807
59847
 
59808
59848
  BufferedCSVReader::BufferedCSVReader(ClientContext &context, BufferedCSVReaderOptions options_p,
59809
59849
  const vector<LogicalType> &requested_types)
59810
- : BufferedCSVReader(FileSystem::GetFileSystem(context), move(options_p), requested_types) {
59850
+ : BufferedCSVReader(FileSystem::GetFileSystem(context), FileSystem::GetFileOpener(context), move(options_p),
59851
+ requested_types) {
59811
59852
  }
59812
59853
 
59813
59854
  void BufferedCSVReader::Initialize(const vector<LogicalType> &requested_types) {
@@ -59839,8 +59880,8 @@ unique_ptr<FileHandle> BufferedCSVReader::OpenCSV(const BufferedCSVReaderOptions
59839
59880
  this->compression = FileCompressionType::GZIP;
59840
59881
  }
59841
59882
 
59842
- auto result =
59843
- fs.OpenFile(options.file_path.c_str(), FileFlags::FILE_FLAGS_READ, FileLockType::NO_LOCK, this->compression);
59883
+ auto result = fs.OpenFile(options.file_path.c_str(), FileFlags::FILE_FLAGS_READ, FileLockType::NO_LOCK,
59884
+ this->compression, this->opener);
59844
59885
  plain_file_source = result->OnDiskFile() && result->CanSeek();
59845
59886
  file_size = result->GetFileSize();
59846
59887
  return result;
@@ -59850,7 +59891,7 @@ unique_ptr<FileHandle> BufferedCSVReader::OpenCSV(const BufferedCSVReaderOptions
59850
59891
  static string GenerateColumnName(const idx_t total_cols, const idx_t col_number, const string &prefix = "column") {
59851
59892
  int max_digits = NumericHelper::UnsignedLength(total_cols - 1);
59852
59893
  int digits = NumericHelper::UnsignedLength(col_number);
59853
- string leading_zeros = string("0", max_digits - digits);
59894
+ string leading_zeros = string(max_digits - digits, '0');
59854
59895
  string value = to_string(col_number);
59855
59896
  return string(prefix + leading_zeros + value);
59856
59897
  }
@@ -61584,10 +61625,10 @@ static void WriteCatalogEntries(stringstream &ss, vector<CatalogEntry *> &entrie
61584
61625
  ss << std::endl;
61585
61626
  }
61586
61627
 
61587
- static void WriteStringStreamToFile(FileSystem &fs, stringstream &ss, const string &path) {
61628
+ static void WriteStringStreamToFile(FileSystem &fs, FileOpener *opener, stringstream &ss, const string &path) {
61588
61629
  auto ss_string = ss.str();
61589
61630
  auto handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE_NEW,
61590
- FileLockType::WRITE_LOCK);
61631
+ FileLockType::WRITE_LOCK, FileSystem::DEFAULT_COMPRESSION, opener);
61591
61632
  fs.Write(*handle, (void *)ss_string.c_str(), ss_string.size());
61592
61633
  handle.reset();
61593
61634
  }
@@ -61641,6 +61682,7 @@ static void WriteCopyStatement(FileSystem &fs, stringstream &ss, TableCatalogEnt
61641
61682
  void PhysicalExport::GetChunkInternal(ExecutionContext &context, DataChunk &chunk, PhysicalOperatorState *state) const {
61642
61683
  auto &ccontext = context.client;
61643
61684
  auto &fs = FileSystem::GetFileSystem(ccontext);
61685
+ auto *opener = FileSystem::GetFileOpener(ccontext);
61644
61686
 
61645
61687
  // gather all catalog types to export
61646
61688
  vector<CatalogEntry *> schemas;
@@ -61680,7 +61722,7 @@ void PhysicalExport::GetChunkInternal(ExecutionContext &context, DataChunk &chun
61680
61722
  WriteCatalogEntries(ss, views);
61681
61723
  WriteCatalogEntries(ss, indexes);
61682
61724
 
61683
- WriteStringStreamToFile(fs, ss, fs.JoinPath(info->file_path, "schema.sql"));
61725
+ WriteStringStreamToFile(fs, opener, ss, fs.JoinPath(info->file_path, "schema.sql"));
61684
61726
 
61685
61727
  // write the load.sql file
61686
61728
  // for every table, we write COPY INTO statement with the specified options
@@ -61690,7 +61732,7 @@ void PhysicalExport::GetChunkInternal(ExecutionContext &context, DataChunk &chun
61690
61732
  auto exported_table_info = kv.second;
61691
61733
  WriteCopyStatement(fs, load_ss, table, *info, exported_table_info, function);
61692
61734
  }
61693
- WriteStringStreamToFile(fs, load_ss, fs.JoinPath(info->file_path, "load.sql"));
61735
+ WriteStringStreamToFile(fs, opener, load_ss, fs.JoinPath(info->file_path, "load.sql"));
61694
61736
  state->finished = true;
61695
61737
  }
61696
61738
 
@@ -76035,7 +76077,9 @@ static void PragmaLogQueryPath(ClientContext &context, const FunctionParameters
76035
76077
  // empty path: clean up query writer
76036
76078
  context.log_query_writer = nullptr;
76037
76079
  } else {
76038
- context.log_query_writer = make_unique<BufferedFileWriter>(FileSystem::GetFileSystem(context), str_val);
76080
+ context.log_query_writer =
76081
+ make_unique<BufferedFileWriter>(FileSystem::GetFileSystem(context), str_val,
76082
+ BufferedFileWriter::DEFAULT_OPEN_FLAGS, context.file_opener.get());
76039
76083
  }
76040
76084
  }
76041
76085
 
@@ -76243,12 +76287,15 @@ string PragmaVersion(ClientContext &context, const FunctionParameters &parameter
76243
76287
 
76244
76288
  string PragmaImportDatabase(ClientContext &context, const FunctionParameters &parameters) {
76245
76289
  auto &fs = FileSystem::GetFileSystem(context);
76290
+ auto *opener = FileSystem::GetFileOpener(context);
76291
+
76246
76292
  string query;
76247
76293
  // read the "shema.sql" and "load.sql" files
76248
76294
  vector<string> files = {"schema.sql", "load.sql"};
76249
76295
  for (auto &file : files) {
76250
76296
  auto file_path = fs.JoinPath(parameters.values[0].ToString(), file);
76251
- auto handle = fs.OpenFile(file_path, FileFlags::FILE_FLAGS_READ);
76297
+ auto handle = fs.OpenFile(file_path, FileFlags::FILE_FLAGS_READ, FileSystem::DEFAULT_LOCK,
76298
+ FileSystem::DEFAULT_COMPRESSION, opener);
76252
76299
  auto fsize = fs.GetFileSize(*handle);
76253
76300
  auto buffer = unique_ptr<char[]>(new char[fsize]);
76254
76301
  fs.Read(*handle, buffer.get(), fsize);
@@ -91223,9 +91270,9 @@ struct LocalReadCSVData : public LocalFunctionData {
91223
91270
  };
91224
91271
 
91225
91272
  struct GlobalWriteCSVData : public GlobalFunctionData {
91226
- GlobalWriteCSVData(FileSystem &fs, const string &file_path) : fs(fs) {
91273
+ GlobalWriteCSVData(FileSystem &fs, const string &file_path, FileOpener *opener) : fs(fs) {
91227
91274
  handle = fs.OpenFile(file_path, FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE_NEW,
91228
- FileLockType::WRITE_LOCK);
91275
+ FileLockType::WRITE_LOCK, FileSystem::DEFAULT_COMPRESSION, opener);
91229
91276
  }
91230
91277
 
91231
91278
  void WriteData(const_data_ptr_t data, idx_t size) {
@@ -91255,7 +91302,8 @@ static unique_ptr<LocalFunctionData> WriteCSVInitializeLocal(ClientContext &cont
91255
91302
  static unique_ptr<GlobalFunctionData> WriteCSVInitializeGlobal(ClientContext &context, FunctionData &bind_data) {
91256
91303
  auto &csv_data = (WriteCSVData &)bind_data;
91257
91304
  auto &options = csv_data.options;
91258
- auto global_data = make_unique<GlobalWriteCSVData>(FileSystem::GetFileSystem(context), csv_data.files[0]);
91305
+ auto global_data = make_unique<GlobalWriteCSVData>(FileSystem::GetFileSystem(context), csv_data.files[0],
91306
+ FileSystem::GetFileOpener(context));
91259
91307
 
91260
91308
  if (options.header) {
91261
91309
  BufferedSerializer serializer;
@@ -96978,6 +97026,61 @@ bool duckdb_value_is_null(duckdb_result *result, idx_t col, idx_t row) {
96978
97026
  return result->columns[col].nullmask[row];
96979
97027
  }
96980
97028
 
97029
+ //===----------------------------------------------------------------------===//
97030
+ // DuckDB
97031
+ //
97032
+ // duckdb/main/client_context_file_opener.hpp
97033
+ //
97034
+ //
97035
+ //===----------------------------------------------------------------------===//
97036
+
97037
+
97038
+
97039
+ //===----------------------------------------------------------------------===//
97040
+ // DuckDB
97041
+ //
97042
+ // duckdb/common/file_opener.hpp
97043
+ //
97044
+ //
97045
+ //===----------------------------------------------------------------------===//
97046
+
97047
+
97048
+
97049
+
97050
+
97051
+ namespace duckdb {
97052
+
97053
+ class Value;
97054
+
97055
+ //! Abstact type that provide client-spcific context to FileSystem.
97056
+ class FileOpener {
97057
+ public:
97058
+ virtual ~FileOpener() {};
97059
+
97060
+ virtual bool TryGetCurrentSetting(const string &key, Value &result) = 0;
97061
+ };
97062
+
97063
+ } // namespace duckdb
97064
+
97065
+ namespace duckdb {
97066
+
97067
+ class ClientContext;
97068
+
97069
+ //! ClientContext-specific FileOpener implemenation.
97070
+ //! This object is owned by ClientContext and never outlives it.
97071
+ class ClientContextFileOpener : public FileOpener {
97072
+ public:
97073
+ explicit ClientContextFileOpener(ClientContext &context_p) : context(context_p) {
97074
+ }
97075
+
97076
+ bool TryGetCurrentSetting(const string &key, Value &result) override;
97077
+
97078
+ private:
97079
+ ClientContext &context;
97080
+ };
97081
+
97082
+ } // namespace duckdb
97083
+
96981
97084
 
96982
97085
 
96983
97086
 
@@ -97428,7 +97531,8 @@ private:
97428
97531
  ClientContext::ClientContext(shared_ptr<DatabaseInstance> database)
97429
97532
  : profiler(make_unique<QueryProfiler>()), query_profiler_history(make_unique<QueryProfilerHistory>()),
97430
97533
  db(move(database)), transaction(db->GetTransactionManager(), *this), interrupted(false), executor(*this),
97431
- temporary_objects(make_unique<SchemaCatalogEntry>(&db->GetCatalog(), TEMP_SCHEMA, true)), open_result(nullptr) {
97534
+ temporary_objects(make_unique<SchemaCatalogEntry>(&db->GetCatalog(), TEMP_SCHEMA, true)),
97535
+ file_opener(make_unique<ClientContextFileOpener>(*this)), open_result(nullptr) {
97432
97536
  std::random_device rd;
97433
97537
  random_engine.seed(rd());
97434
97538
 
@@ -97895,7 +97999,8 @@ void ClientContext::LogQueryInternal(ClientContextLock &, const string &query) {
97895
97999
  #ifdef DUCKDB_FORCE_QUERY_LOG
97896
98000
  try {
97897
98001
  string log_path(DUCKDB_FORCE_QUERY_LOG);
97898
- log_query_writer = make_unique<BufferedFileWriter>(FileSystem::GetFileSystem(*this), log_path);
98002
+ log_query_writer = make_unique<BufferedFileWriter>(
98003
+ FileSystem::GetFileSystem(*this), log_path, BufferedFileWriter::DEFAULT_OPEN_FLAGS, file_opener.get());
97899
98004
  } catch (...) {
97900
98005
  return;
97901
98006
  }
@@ -98315,6 +98420,16 @@ bool ClientContext::TryGetCurrentSetting(const std::string &key, Value &result)
98315
98420
 
98316
98421
 
98317
98422
 
98423
+ namespace duckdb {
98424
+
98425
+ bool ClientContextFileOpener::TryGetCurrentSetting(const string &key, Value &result) {
98426
+ return context.TryGetCurrentSetting(key, result);
98427
+ }
98428
+
98429
+ } // namespace duckdb
98430
+
98431
+
98432
+
98318
98433
  namespace duckdb {
98319
98434
 
98320
98435
  static ConfigurationOption internal_options[] = {
@@ -145876,6 +145991,29 @@ idx_t LocalStorage::Delete(DataTable *table, Vector &row_ids, idx_t count) {
145876
145991
  idx_t chunk_idx = GetChunk(row_ids);
145877
145992
  D_ASSERT(chunk_idx < storage->collection.ChunkCount());
145878
145993
 
145994
+ // delete from unique indices (if any)
145995
+ if (!storage->indexes.empty()) {
145996
+ // Index::Delete assumes that ALL rows are being deleted, so
145997
+ // Slice out the rows that are being deleted from the storage Chunk
145998
+ auto &chunk = storage->collection.GetChunk(chunk_idx);
145999
+
146000
+ VectorData row_ids_data;
146001
+ row_ids.Orrify(count, row_ids_data);
146002
+ auto row_identifiers = (const row_t *)row_ids_data.data;
146003
+ SelectionVector sel(count);
146004
+ for (idx_t i = 0; i < count; ++i) {
146005
+ const auto idx = row_ids_data.sel->get_index(i);
146006
+ sel.set_index(i, row_identifiers[idx] - MAX_ROW_ID);
146007
+ }
146008
+
146009
+ DataChunk deleted;
146010
+ deleted.InitializeEmpty(chunk.GetTypes());
146011
+ deleted.Slice(chunk, sel, count);
146012
+ for (auto &index : storage->indexes) {
146013
+ index->Delete(deleted, row_ids);
146014
+ }
146015
+ }
146016
+
145879
146017
  // get a pointer to the deleted entries for this chunk
145880
146018
  bool *deleted;
145881
146019
  auto entry = storage->deleted_entries.find(chunk_idx);
@@ -146392,7 +146530,7 @@ SingleFileBlockManager::SingleFileBlockManager(DatabaseInstance &db, string path
146392
146530
  flags = FileFlags::FILE_FLAGS_READ;
146393
146531
  lock = FileLockType::READ_LOCK;
146394
146532
  } else {
146395
- flags = FileFlags::FILE_FLAGS_WRITE;
146533
+ flags = FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_READ;
146396
146534
  lock = FileLockType::WRITE_LOCK;
146397
146535
  if (create_new) {
146398
146536
  flags |= FileFlags::FILE_FLAGS_FILE_CREATE;
package/src/duckdb.hpp CHANGED
@@ -10,8 +10,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
10
10
 
11
11
  #pragma once
12
12
  #define DUCKDB_AMALGAMATION 1
13
- #define DUCKDB_SOURCE_ID "57a9aff40"
14
- #define DUCKDB_VERSION "0.2.10-dev325"
13
+ #define DUCKDB_SOURCE_ID "ee3e405a9"
14
+ #define DUCKDB_VERSION "0.2.10-dev337"
15
15
  //===----------------------------------------------------------------------===//
16
16
  // DuckDB
17
17
  //
@@ -1710,6 +1710,7 @@ enum class FileCompressionType : uint8_t { AUTO_DETECT = 0, UNCOMPRESSED = 1, GZ
1710
1710
  namespace duckdb {
1711
1711
  class ClientContext;
1712
1712
  class DatabaseInstance;
1713
+ class FileOpener;
1713
1714
  class FileSystem;
1714
1715
 
1715
1716
  enum class FileType {
@@ -1787,12 +1788,15 @@ public:
1787
1788
  }
1788
1789
 
1789
1790
  public:
1791
+ static constexpr FileLockType DEFAULT_LOCK = FileLockType::NO_LOCK;
1792
+ static constexpr FileCompressionType DEFAULT_COMPRESSION = FileCompressionType::UNCOMPRESSED;
1790
1793
  static FileSystem &GetFileSystem(ClientContext &context);
1791
1794
  static FileSystem &GetFileSystem(DatabaseInstance &db);
1795
+ static FileOpener *GetFileOpener(ClientContext &context);
1792
1796
 
1793
- virtual unique_ptr<FileHandle> OpenFile(const string &path, uint8_t flags,
1794
- FileLockType lock = FileLockType::NO_LOCK,
1795
- FileCompressionType compression = FileCompressionType::UNCOMPRESSED);
1797
+ virtual unique_ptr<FileHandle> OpenFile(const string &path, uint8_t flags, FileLockType lock = DEFAULT_LOCK,
1798
+ FileCompressionType compression = DEFAULT_COMPRESSION,
1799
+ FileOpener *opener = nullptr);
1796
1800
 
1797
1801
  //! Read exactly nr_bytes from the specified location in the file. Fails if nr_bytes could not be read. This is
1798
1802
  //! equivalent to calling SetFilePointer(location) followed by calling Read().
@@ -1889,10 +1893,12 @@ namespace duckdb {
1889
1893
 
1890
1894
  class BufferedFileWriter : public Serializer {
1891
1895
  public:
1896
+ static constexpr uint8_t DEFAULT_OPEN_FLAGS = FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE;
1897
+
1892
1898
  //! Serializes to a buffer allocated by the serializer, will expand when
1893
1899
  //! writing past the initial threshold
1894
- BufferedFileWriter(FileSystem &fs, const string &path,
1895
- uint8_t open_flags = FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE);
1900
+ BufferedFileWriter(FileSystem &fs, const string &path, uint8_t open_flags = DEFAULT_OPEN_FLAGS,
1901
+ FileOpener *opener = nullptr);
1896
1902
 
1897
1903
  FileSystem &fs;
1898
1904
  unique_ptr<data_t[]> data;
@@ -13058,6 +13064,7 @@ class Appender;
13058
13064
  class Catalog;
13059
13065
  class ChunkCollection;
13060
13066
  class DatabaseInstance;
13067
+ class FileOpener;
13061
13068
  class LogicalOperator;
13062
13069
  class PreparedStatementData;
13063
13070
  class Relation;
@@ -13129,6 +13136,8 @@ public:
13129
13136
  //! The schema search path, in order by which entries are searched if no schema entry is provided
13130
13137
  vector<string> catalog_search_path = {TEMP_SCHEMA, DEFAULT_SCHEMA, "pg_catalog"};
13131
13138
 
13139
+ unique_ptr<FileOpener> file_opener;
13140
+
13132
13141
  public:
13133
13142
  DUCKDB_API Transaction &ActiveTransaction() {
13134
13143
  return transaction.ActiveTransaction();