duckdb 0.5.2-dev250.0 → 0.5.2-dev269.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.5.2-dev250.0",
4
+ "version": "0.5.2-dev269.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -66611,6 +66611,13 @@ struct DefaultExtension {
66611
66611
  bool statically_loaded;
66612
66612
  };
66613
66613
 
66614
+ struct ExtensionInitResult {
66615
+ string filename;
66616
+ string basename;
66617
+
66618
+ void *lib_hdl;
66619
+ };
66620
+
66614
66621
  class ExtensionHelper {
66615
66622
  public:
66616
66623
  static void LoadAllExtensions(DuckDB &db);
@@ -66627,8 +66634,13 @@ public:
66627
66634
 
66628
66635
  static const vector<string> GetPublicKeys();
66629
66636
 
66637
+ static unique_ptr<ReplacementOpenData> ReplacementOpenPre(const string &extension, DBConfig &config);
66638
+ static void ReplacementOpenPost(ClientContext &context, const string &extension, DatabaseInstance &instance,
66639
+ ReplacementOpenData *open_data);
66640
+
66630
66641
  private:
66631
66642
  static const vector<string> PathComponents();
66643
+ static ExtensionInitResult InitialLoad(DBConfig &context, FileOpener *opener, const string &extension);
66632
66644
  //! For tagged releases we use the tag, else we use the git commit hash
66633
66645
  static const string GetVersionDirectoryName();
66634
66646
  //! Version tags occur with and without 'v', tag in extension path is always with 'v'
@@ -129389,6 +129401,27 @@ bool Connection::HasActiveTransaction() {
129389
129401
 
129390
129402
 
129391
129403
 
129404
+ //===----------------------------------------------------------------------===//
129405
+ // DuckDB
129406
+ //
129407
+ // duckdb/main/extension_helper.hpp
129408
+ //
129409
+ //
129410
+ //===----------------------------------------------------------------------===//
129411
+
129412
+
129413
+
129414
+
129415
+
129416
+ namespace duckdb {
129417
+
129418
+ class ExtensionPrefixReplacementOpen : public ReplacementOpen {
129419
+ public:
129420
+ ExtensionPrefixReplacementOpen();
129421
+ };
129422
+
129423
+ } // namespace duckdb
129424
+
129392
129425
 
129393
129426
 
129394
129427
  #ifndef DUCKDB_NO_THREADS
@@ -129399,6 +129432,7 @@ namespace duckdb {
129399
129432
 
129400
129433
  DBConfig::DBConfig() {
129401
129434
  compression_functions = make_unique<CompressionFunctionSet>();
129435
+ replacement_opens.push_back(ExtensionPrefixReplacementOpen());
129402
129436
  cast_functions = make_unique<CastFunctionSet>();
129403
129437
  }
129404
129438
 
@@ -129488,30 +129522,47 @@ ConnectionManager &ConnectionManager::Get(ClientContext &context) {
129488
129522
  return ConnectionManager::Get(DatabaseInstance::GetDatabase(context));
129489
129523
  }
129490
129524
 
129491
- void DatabaseInstance::Initialize(const char *path, DBConfig *new_config) {
129492
- if (new_config) {
129493
- // user-supplied configuration
129494
- Configure(*new_config);
129495
- } else {
129496
- // default configuration
129497
- DBConfig config;
129498
- Configure(config);
129525
+ void DatabaseInstance::Initialize(const char *database_path, DBConfig *user_config) {
129526
+ DBConfig default_config;
129527
+ DBConfig *config_ptr = &default_config;
129528
+ if (user_config) {
129529
+ config_ptr = user_config;
129499
129530
  }
129500
- if (config.options.temporary_directory.empty() && path) {
129531
+
129532
+ if (config_ptr->options.temporary_directory.empty() && database_path) {
129501
129533
  // no directory specified: use default temp path
129502
- config.options.temporary_directory = string(path) + ".tmp";
129534
+ config_ptr->options.temporary_directory = string(database_path) + ".tmp";
129503
129535
 
129504
129536
  // special treatment for in-memory mode
129505
- if (strcmp(path, ":memory:") == 0) {
129506
- config.options.temporary_directory = ".tmp";
129537
+ if (strcmp(database_path, ":memory:") == 0) {
129538
+ config_ptr->options.temporary_directory = ".tmp";
129507
129539
  }
129508
129540
  }
129509
- if (new_config && !new_config->options.use_temporary_directory) {
129541
+
129542
+ if (database_path) {
129543
+ config_ptr->options.database_path = database_path;
129544
+ } else {
129545
+ config_ptr->options.database_path.clear();
129546
+ }
129547
+
129548
+ for (auto &open : config_ptr->replacement_opens) {
129549
+ if (open.pre_func) {
129550
+ open.data = open.pre_func(*config_ptr, open.static_data.get());
129551
+ if (open.data) {
129552
+ break;
129553
+ }
129554
+ }
129555
+ }
129556
+ Configure(*config_ptr);
129557
+
129558
+ if (user_config && !user_config->options.use_temporary_directory) {
129510
129559
  // temporary directories explicitly disabled
129511
129560
  config.options.temporary_directory = string();
129512
129561
  }
129513
129562
 
129514
- storage = make_unique<StorageManager>(*this, path ? string(path) : string(),
129563
+ // config.create_storage_manager(config.options.database_path,
129564
+ // config.options.access_mode == AccessMode::READ_ONLY);
129565
+ storage = make_unique<StorageManager>(*this, config.options.database_path,
129515
129566
  config.options.access_mode == AccessMode::READ_ONLY);
129516
129567
  catalog = make_unique<Catalog>(*this);
129517
129568
  transaction_manager = make_unique<TransactionManager>(*this);
@@ -129524,6 +129575,13 @@ void DatabaseInstance::Initialize(const char *path, DBConfig *new_config) {
129524
129575
 
129525
129576
  // only increase thread count after storage init because we get races on catalog otherwise
129526
129577
  scheduler->SetThreads(config.options.maximum_threads);
129578
+
129579
+ for (auto &open : config.replacement_opens) {
129580
+ if (open.post_func && open.data) {
129581
+ open.post_func(*this, open.data.get());
129582
+ break;
129583
+ }
129584
+ }
129527
129585
  }
129528
129586
 
129529
129587
  DuckDB::DuckDB(const char *path, DBConfig *new_config) : instance(make_shared<DatabaseInstance>()) {
@@ -129583,6 +129641,7 @@ Allocator &Allocator::Get(DatabaseInstance &db) {
129583
129641
  }
129584
129642
 
129585
129643
  void DatabaseInstance::Configure(DBConfig &new_config) {
129644
+ config.options.database_path = new_config.options.database_path;
129586
129645
  config.options.access_mode = AccessMode::READ_WRITE;
129587
129646
  if (new_config.options.access_mode != AccessMode::UNDEFINED) {
129588
129647
  config.options.access_mode = new_config.options.access_mode;
@@ -129624,6 +129683,7 @@ void DatabaseInstance::Configure(DBConfig &new_config) {
129624
129683
  config.options.enable_external_access = new_config.options.enable_external_access;
129625
129684
  config.options.allow_unsigned_extensions = new_config.options.allow_unsigned_extensions;
129626
129685
  config.replacement_scans = move(new_config.replacement_scans);
129686
+ config.replacement_opens = move(new_config.replacement_opens); // TODO is this okay?
129627
129687
  config.options.initialize_default_database = new_config.options.initialize_default_database;
129628
129688
  config.options.disabled_optimizers = move(new_config.options.disabled_optimizers);
129629
129689
  config.parser_extensions = move(new_config.parser_extensions);
@@ -138575,6 +138635,8 @@ public:
138575
138635
  // LICENSE_CHANGE_END
138576
138636
 
138577
138637
 
138638
+
138639
+
138578
138640
  namespace duckdb {
138579
138641
 
138580
138642
  //===--------------------------------------------------------------------===//
@@ -138592,18 +138654,17 @@ static T LoadFunctionFromDLL(void *dll, const string &function_name, const strin
138592
138654
  return (T)function;
138593
138655
  }
138594
138656
 
138595
- void ExtensionHelper::LoadExternalExtension(ClientContext &context, const string &extension) {
138596
- auto &db = DatabaseInstance::GetDatabase(context);
138597
- auto &config = DBConfig::GetConfig(context);
138657
+ ExtensionInitResult ExtensionHelper::InitialLoad(DBConfig &config, FileOpener *opener, const string &extension) {
138598
138658
  if (!config.options.enable_external_access) {
138599
138659
  throw PermissionException("Loading external extensions is disabled through configuration");
138600
138660
  }
138601
- auto &fs = FileSystem::GetFileSystem(context);
138661
+ VirtualFileSystem fallback_file_system; // config may not contain one yet
138662
+ auto &fs = config.file_system ? *config.file_system : fallback_file_system;
138602
138663
  auto filename = fs.ConvertSeparators(extension);
138603
138664
 
138604
138665
  // shorthand case
138605
138666
  if (!StringUtil::Contains(extension, ".") && !StringUtil::Contains(extension, fs.PathSeparator())) {
138606
- string local_path = fs.GetHomeDirectory(FileSystem::GetFileOpener(context));
138667
+ string local_path = fs.GetHomeDirectory(opener);
138607
138668
  auto path_components = PathComponents();
138608
138669
  for (auto &path_ele : path_components) {
138609
138670
  local_path = fs.JoinPath(local_path, path_ele);
@@ -138653,13 +138714,10 @@ void ExtensionHelper::LoadExternalExtension(ClientContext &context, const string
138653
138714
  }
138654
138715
 
138655
138716
  auto basename = fs.ExtractBaseName(filename);
138656
- auto init_fun_name = basename + "_init";
138657
- auto version_fun_name = basename + "_version";
138658
138717
 
138659
- ext_init_fun_t init_fun;
138660
138718
  ext_version_fun_t version_fun;
138719
+ auto version_fun_name = basename + "_version";
138661
138720
 
138662
- init_fun = LoadFunctionFromDLL<ext_init_fun_t>(lib_hdl, init_fun_name, filename);
138663
138721
  version_fun = LoadFunctionFromDLL<ext_version_fun_t>(lib_hdl, version_fun_name, filename);
138664
138722
 
138665
138723
  std::string engine_version = std::string(DuckDB::LibraryVersion());
@@ -138685,11 +138743,59 @@ void ExtensionHelper::LoadExternalExtension(ClientContext &context, const string
138685
138743
  extension_version, engine_version);
138686
138744
  }
138687
138745
 
138746
+ ExtensionInitResult res;
138747
+ res.basename = basename;
138748
+ res.filename = filename;
138749
+ res.lib_hdl = lib_hdl;
138750
+ return res;
138751
+ }
138752
+
138753
+ void ExtensionHelper::LoadExternalExtension(ClientContext &context, const string &extension) {
138754
+ auto &db = DatabaseInstance::GetDatabase(context);
138755
+
138756
+ auto res = InitialLoad(DBConfig::GetConfig(context), FileSystem::GetFileOpener(context), extension);
138757
+ auto init_fun_name = res.basename + "_init";
138758
+
138759
+ ext_init_fun_t init_fun;
138760
+ init_fun = LoadFunctionFromDLL<ext_init_fun_t>(res.lib_hdl, init_fun_name, res.filename);
138761
+
138688
138762
  try {
138689
138763
  (*init_fun)(db);
138690
138764
  } catch (std::exception &e) {
138691
138765
  throw InvalidInputException("Initialization function \"%s\" from file \"%s\" threw an exception: \"%s\"",
138692
- init_fun_name, filename, e.what());
138766
+ init_fun_name, res.filename, e.what());
138767
+ }
138768
+ }
138769
+
138770
+ unique_ptr<ReplacementOpenData> ExtensionHelper::ReplacementOpenPre(const string &extension, DBConfig &config) {
138771
+
138772
+ auto res = InitialLoad(config, nullptr, extension); // TODO opener
138773
+ auto init_fun_name = res.basename + "_replacement_open_pre";
138774
+
138775
+ replacement_open_pre_t open_pre_fun;
138776
+ open_pre_fun = LoadFunctionFromDLL<replacement_open_pre_t>(res.lib_hdl, init_fun_name, res.filename);
138777
+
138778
+ try {
138779
+ return (*open_pre_fun)(config, nullptr);
138780
+ } catch (std::exception &e) {
138781
+ throw InvalidInputException("Initialization function \"%s\" from file \"%s\" threw an exception: \"%s\"",
138782
+ init_fun_name, res.filename, e.what());
138783
+ }
138784
+ }
138785
+
138786
+ void ExtensionHelper::ReplacementOpenPost(ClientContext &context, const string &extension, DatabaseInstance &instance,
138787
+ ReplacementOpenData *open_data) {
138788
+ auto res = InitialLoad(DBConfig::GetConfig(context), FileSystem::GetFileOpener(context), extension);
138789
+ auto init_fun_name = res.basename + "_replacement_open_post";
138790
+
138791
+ replacement_open_post_t open_post_fun;
138792
+ open_post_fun = LoadFunctionFromDLL<replacement_open_post_t>(res.lib_hdl, init_fun_name, res.filename);
138793
+
138794
+ try {
138795
+ (*open_post_fun)(instance, open_data);
138796
+ } catch (std::exception &e) {
138797
+ throw InvalidInputException("Initialization function \"%s\" from file \"%s\" threw an exception: \"%s\"",
138798
+ init_fun_name, res.filename, e.what());
138693
138799
  }
138694
138800
  }
138695
138801
 
@@ -138706,6 +138812,61 @@ Extension::~Extension() {
138706
138812
 
138707
138813
 
138708
138814
 
138815
+
138816
+ namespace duckdb {
138817
+
138818
+ struct ExtensionPrefixOpenData : public ReplacementOpenData {
138819
+ ExtensionPrefixOpenData(string extension, string path, unique_ptr<ReplacementOpenData> data)
138820
+ : extension(move(extension)), path(move(path)), data(move(data)) {
138821
+ }
138822
+ string extension;
138823
+ string path;
138824
+ unique_ptr<ReplacementOpenData> data;
138825
+ };
138826
+
138827
+ static unique_ptr<ReplacementOpenData> ExtensionPrefixPreOpen(DBConfig &config, ReplacementOpenStaticData *) {
138828
+ auto path = config.options.database_path;
138829
+ auto first_colon = path.find(':');
138830
+ if (first_colon == string::npos || first_colon < 2) { // needs to be at least two characters because windows c: ...
138831
+ return nullptr;
138832
+ }
138833
+ auto extension = path.substr(0, first_colon);
138834
+ D_ASSERT(extension.size() > 1);
138835
+ // needs to be alphanumeric
138836
+ for (auto &ch : extension) {
138837
+ if (!isalnum(ch) && ch != '_') {
138838
+ return nullptr;
138839
+ }
138840
+ }
138841
+ auto extension_data = ExtensionHelper::ReplacementOpenPre(extension, config);
138842
+ if (extension_data) {
138843
+ return make_unique<ExtensionPrefixOpenData>(extension, path, move(extension_data));
138844
+ }
138845
+ return nullptr;
138846
+ }
138847
+
138848
+ static void ExtensionPrefixPostOpen(DatabaseInstance &instance, ReplacementOpenData *open_data) {
138849
+ if (!open_data) {
138850
+ return;
138851
+ }
138852
+ D_ASSERT(open_data);
138853
+ auto prefix_open_data = (ExtensionPrefixOpenData *)open_data;
138854
+
138855
+ Connection con(instance);
138856
+ ExtensionHelper::LoadExternalExtension(*con.context, prefix_open_data->extension);
138857
+ ExtensionHelper::ReplacementOpenPost(*con.context, prefix_open_data->extension, instance,
138858
+ prefix_open_data->data.get());
138859
+ }
138860
+
138861
+ ExtensionPrefixReplacementOpen::ExtensionPrefixReplacementOpen()
138862
+ : ReplacementOpen(ExtensionPrefixPreOpen, ExtensionPrefixPostOpen) {
138863
+ }
138864
+
138865
+ } // namespace duckdb
138866
+
138867
+
138868
+
138869
+
138709
138870
  namespace duckdb {
138710
138871
 
138711
138872
  MaterializedQueryResult::MaterializedQueryResult(StatementType statement_type, StatementProperties properties,
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 "7389dcf91"
15
- #define DUCKDB_VERSION "v0.5.2-dev250"
14
+ #define DUCKDB_SOURCE_ID "4ad9877f0"
15
+ #define DUCKDB_VERSION "v0.5.2-dev269"
16
16
  //===----------------------------------------------------------------------===//
17
17
  // DuckDB
18
18
  //
@@ -23916,6 +23916,52 @@ struct ReplacementScan {
23916
23916
 
23917
23917
  } // namespace duckdb
23918
23918
 
23919
+ //===----------------------------------------------------------------------===//
23920
+ // DuckDB
23921
+ //
23922
+ // duckdb/function/replacement_scan.hpp
23923
+ //
23924
+ //
23925
+ //===----------------------------------------------------------------------===//
23926
+
23927
+
23928
+
23929
+
23930
+
23931
+ namespace duckdb {
23932
+
23933
+ class DatabaseInstance;
23934
+ struct DBConfig;
23935
+
23936
+ struct ReplacementOpenData {
23937
+ virtual ~ReplacementOpenData() {
23938
+ }
23939
+ };
23940
+
23941
+ struct ReplacementOpenStaticData {
23942
+ virtual ~ReplacementOpenStaticData() {
23943
+ }
23944
+ };
23945
+
23946
+ typedef unique_ptr<ReplacementOpenData> (*replacement_open_pre_t)(DBConfig &config,
23947
+ ReplacementOpenStaticData *static_data);
23948
+ typedef void (*replacement_open_post_t)(DatabaseInstance &instance, ReplacementOpenData *open_data);
23949
+
23950
+ struct ReplacementOpen {
23951
+ explicit ReplacementOpen(replacement_open_pre_t pre_func, replacement_open_post_t post_func)
23952
+ : pre_func(pre_func), post_func(post_func), data(nullptr) {
23953
+ }
23954
+
23955
+ replacement_open_pre_t pre_func;
23956
+ replacement_open_post_t post_func;
23957
+
23958
+ unique_ptr<ReplacementOpenData> data;
23959
+
23960
+ shared_ptr<ReplacementOpenStaticData> static_data;
23961
+ };
23962
+
23963
+ } // namespace duckdb
23964
+
23919
23965
 
23920
23966
 
23921
23967
  //===----------------------------------------------------------------------===//
@@ -24180,6 +24226,8 @@ struct ExtensionOption {
24180
24226
  };
24181
24227
 
24182
24228
  struct DBConfigOptions {
24229
+ //! Database file path. May be empty for in-memory mode
24230
+ string database_path;
24183
24231
  //! Access mode of the database (AUTOMATIC, READ_ONLY or READ_WRITE)
24184
24232
  AccessMode access_mode = AccessMode::AUTOMATIC;
24185
24233
  //! Checkpoint when WAL reaches this size (default: 16MB)
@@ -24243,6 +24291,10 @@ public:
24243
24291
 
24244
24292
  //! Replacement table scans are automatically attempted when a table name cannot be found in the schema
24245
24293
  vector<ReplacementScan> replacement_scans;
24294
+
24295
+ //! Replacement open handlers are callbacks that run pre and post database initialization
24296
+ vector<ReplacementOpen> replacement_opens;
24297
+
24246
24298
  //! Extra parameters that can be SET for loaded extensions
24247
24299
  case_insensitive_map_t<ExtensionOption> extension_parameters;
24248
24300
  //! The FileSystem to use, can be overwritten to allow for injecting custom file systems for testing purposes (e.g.