duckdb 0.8.2-dev3949.0 → 0.8.2-dev3989.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/duckdb_extension_config.cmake +1 -1
- package/package.json +1 -1
- package/src/duckdb/src/common/file_buffer.cpp +1 -1
- package/src/duckdb/src/function/cast/vector_cast_helpers.cpp +7 -2
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/main/extension_helper.hpp +7 -3
- package/src/duckdb/src/main/database.cpp +1 -1
- package/src/duckdb/src/main/extension/extension_install.cpp +30 -17
- package/src/duckdb/src/main/extension/extension_load.cpp +36 -7
@@ -4,7 +4,7 @@
|
|
4
4
|
#
|
5
5
|
# This is the default extension configuration for NodeJS builds. Basically it means that all these extensions are
|
6
6
|
# "baked in" to the NodeJS binaries Note that the configuration here is only when building Node using the main
|
7
|
-
# CMakeLists.txt file with the `
|
7
|
+
# CMakeLists.txt file with the `BUILD_NODE` variable.
|
8
8
|
# TODO: unify this by making setup.py also use this configuration, making this the config for all Node builds
|
9
9
|
duckdb_extension_load(json)
|
10
10
|
duckdb_extension_load(icu)
|
package/package.json
CHANGED
@@ -68,7 +68,7 @@ FileBuffer::MemoryRequirement FileBuffer::CalculateMemory(uint64_t user_size) {
|
|
68
68
|
result.alloc_size = user_size;
|
69
69
|
} else {
|
70
70
|
result.header_size = Storage::BLOCK_HEADER_SIZE;
|
71
|
-
result.alloc_size = AlignValue<
|
71
|
+
result.alloc_size = AlignValue<idx_t, Storage::SECTOR_SIZE>(result.header_size + user_size);
|
72
72
|
}
|
73
73
|
return result;
|
74
74
|
}
|
@@ -98,6 +98,9 @@ struct SplitStringListOperation {
|
|
98
98
|
child_start++;
|
99
99
|
return;
|
100
100
|
}
|
101
|
+
if (start_pos > pos) {
|
102
|
+
pos = start_pos;
|
103
|
+
}
|
101
104
|
child_data[child_start] = StringVector::AddString(child, buf + start_pos, pos - start_pos);
|
102
105
|
child_start++;
|
103
106
|
}
|
@@ -109,6 +112,7 @@ static bool SplitStringListInternal(const string_t &input, OP &state) {
|
|
109
112
|
idx_t len = input.GetSize();
|
110
113
|
idx_t lvl = 1;
|
111
114
|
idx_t pos = 0;
|
115
|
+
bool seen_value = false;
|
112
116
|
|
113
117
|
SkipWhitespace(buf, pos, len);
|
114
118
|
if (pos == len || buf[pos] != '[') {
|
@@ -132,9 +136,10 @@ static bool SplitStringListInternal(const string_t &input, OP &state) {
|
|
132
136
|
while (StringUtil::CharacterIsSpace(buf[pos - trailing_whitespace - 1])) {
|
133
137
|
trailing_whitespace++;
|
134
138
|
}
|
135
|
-
if (
|
139
|
+
if (buf[pos] != ']' || start_pos != pos || seen_value) {
|
136
140
|
state.HandleValue(buf, start_pos, pos - trailing_whitespace);
|
137
|
-
|
141
|
+
seen_value = true;
|
142
|
+
}
|
138
143
|
if (buf[pos] == ']') {
|
139
144
|
lvl--;
|
140
145
|
break;
|
@@ -1,8 +1,8 @@
|
|
1
1
|
#ifndef DUCKDB_VERSION
|
2
|
-
#define DUCKDB_VERSION "0.8.2-
|
2
|
+
#define DUCKDB_VERSION "0.8.2-dev3989"
|
3
3
|
#endif
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
5
|
+
#define DUCKDB_SOURCE_ID "a7a88cb691"
|
6
6
|
#endif
|
7
7
|
#include "duckdb/function/table/system_functions.hpp"
|
8
8
|
#include "duckdb/main/database.hpp"
|
@@ -46,13 +46,16 @@ public:
|
|
46
46
|
static void InstallExtension(DBConfig &config, FileSystem &fs, const string &extension, bool force_install,
|
47
47
|
const string &respository = "");
|
48
48
|
static void LoadExternalExtension(ClientContext &context, const string &extension);
|
49
|
-
static void LoadExternalExtension(DatabaseInstance &db, FileSystem &fs, const string &extension
|
49
|
+
static void LoadExternalExtension(DatabaseInstance &db, FileSystem &fs, const string &extension,
|
50
|
+
optional_ptr<const ClientConfig> client_config);
|
50
51
|
|
51
52
|
//! Autoload an extension by name. Depending on the current settings, this will either load or install+load
|
52
53
|
static void AutoLoadExtension(ClientContext &context, const string &extension_name);
|
53
54
|
|
54
55
|
static string ExtensionDirectory(ClientContext &context);
|
55
56
|
static string ExtensionDirectory(DBConfig &config, FileSystem &fs);
|
57
|
+
static string ExtensionUrlTemplate(optional_ptr<const ClientConfig> config, const string &repository);
|
58
|
+
static string ExtensionFinalizeUrlTemplate(const string &url, const string &name);
|
56
59
|
|
57
60
|
static idx_t DefaultExtensionCount();
|
58
61
|
static DefaultExtension GetDefaultExtension(idx_t index);
|
@@ -101,9 +104,10 @@ private:
|
|
101
104
|
const string &repository);
|
102
105
|
static const vector<string> PathComponents();
|
103
106
|
static bool AllowAutoInstall(const string &extension);
|
104
|
-
static ExtensionInitResult InitialLoad(DBConfig &config, FileSystem &fs, const string &extension
|
107
|
+
static ExtensionInitResult InitialLoad(DBConfig &config, FileSystem &fs, const string &extension,
|
108
|
+
optional_ptr<const ClientConfig> client_config);
|
105
109
|
static bool TryInitialLoad(DBConfig &config, FileSystem &fs, const string &extension, ExtensionInitResult &result,
|
106
|
-
string &error);
|
110
|
+
string &error, optional_ptr<const ClientConfig> client_config);
|
107
111
|
//! For tagged releases we use the tag, else we use the git commit hash
|
108
112
|
static const string GetVersionDirectoryName();
|
109
113
|
//! Version tags occur with and without 'v', tag in extension path is always with 'v'
|
@@ -234,7 +234,7 @@ void DatabaseInstance::Initialize(const char *database_path, DBConfig *user_conf
|
|
234
234
|
if (!config.file_system) {
|
235
235
|
throw InternalException("No file system!?");
|
236
236
|
}
|
237
|
-
ExtensionHelper::LoadExternalExtension(*this, *config.file_system, config.options.database_type);
|
237
|
+
ExtensionHelper::LoadExternalExtension(*this, *config.file_system, config.options.database_type, nullptr);
|
238
238
|
}
|
239
239
|
|
240
240
|
if (!config.options.unrecognized_options.empty()) {
|
@@ -45,7 +45,7 @@ const vector<string> ExtensionHelper::PathComponents() {
|
|
45
45
|
|
46
46
|
string ExtensionHelper::ExtensionDirectory(DBConfig &config, FileSystem &fs) {
|
47
47
|
#ifdef WASM_LOADABLE_EXTENSIONS
|
48
|
-
|
48
|
+
static_assert(0, "ExtensionDirectory functionality is not supported in duckdb-wasm");
|
49
49
|
#endif
|
50
50
|
string extension_directory;
|
51
51
|
if (!config.options.extension_directory.empty()) { // create the extension directory if not present
|
@@ -157,6 +157,32 @@ void WriteExtensionFileToDisk(FileSystem &fs, const string &path, void *data, id
|
|
157
157
|
target_file.reset();
|
158
158
|
}
|
159
159
|
|
160
|
+
string ExtensionHelper::ExtensionUrlTemplate(optional_ptr<const ClientConfig> client_config, const string &repository) {
|
161
|
+
string default_endpoint = "http://extensions.duckdb.org";
|
162
|
+
string versioned_path = "/${REVISION}/${PLATFORM}/${NAME}.duckdb_extension.gz";
|
163
|
+
#ifdef WASM_LOADABLE_EXTENSIONS
|
164
|
+
versioned_path = "/duckdb-wasm" + versioned_path;
|
165
|
+
#endif
|
166
|
+
string custom_endpoint = client_config ? client_config->custom_extension_repo : string();
|
167
|
+
string endpoint;
|
168
|
+
if (!repository.empty()) {
|
169
|
+
endpoint = repository;
|
170
|
+
} else if (!custom_endpoint.empty()) {
|
171
|
+
endpoint = custom_endpoint;
|
172
|
+
} else {
|
173
|
+
endpoint = default_endpoint;
|
174
|
+
}
|
175
|
+
string url_template = endpoint + versioned_path;
|
176
|
+
return url_template;
|
177
|
+
}
|
178
|
+
|
179
|
+
string ExtensionHelper::ExtensionFinalizeUrlTemplate(const string &url_template, const string &extension_name) {
|
180
|
+
auto url = StringUtil::Replace(url_template, "${REVISION}", GetVersionDirectoryName());
|
181
|
+
url = StringUtil::Replace(url, "${PLATFORM}", DuckDB::Platform());
|
182
|
+
url = StringUtil::Replace(url, "${NAME}", extension_name);
|
183
|
+
return url;
|
184
|
+
}
|
185
|
+
|
160
186
|
void ExtensionHelper::InstallExtensionInternal(DBConfig &config, ClientConfig *client_config, FileSystem &fs,
|
161
187
|
const string &local_path, const string &extension, bool force_install,
|
162
188
|
const string &repository) {
|
@@ -197,27 +223,14 @@ void ExtensionHelper::InstallExtensionInternal(DBConfig &config, ClientConfig *c
|
|
197
223
|
throw BinderException("Remote extension installation is disabled through configuration");
|
198
224
|
#else
|
199
225
|
|
200
|
-
string
|
201
|
-
string custom_endpoint = client_config ? client_config->custom_extension_repo : string();
|
202
|
-
string endpoint;
|
203
|
-
if (!repository.empty()) {
|
204
|
-
endpoint = repository;
|
205
|
-
} else if (!custom_endpoint.empty()) {
|
206
|
-
endpoint = custom_endpoint;
|
207
|
-
} else {
|
208
|
-
endpoint = "http://extensions.duckdb.org";
|
209
|
-
}
|
210
|
-
|
211
|
-
string url_template = endpoint + versioned_path;
|
226
|
+
string url_template = ExtensionUrlTemplate(client_config, repository);
|
212
227
|
|
213
228
|
if (is_http_url) {
|
214
229
|
url_template = extension;
|
215
230
|
extension_name = "";
|
216
231
|
}
|
217
232
|
|
218
|
-
|
219
|
-
url = StringUtil::Replace(url, "${PLATFORM}", DuckDB::Platform());
|
220
|
-
url = StringUtil::Replace(url, "${NAME}", extension_name);
|
233
|
+
string url = ExtensionFinalizeUrlTemplate(url_template, extension_name);
|
221
234
|
|
222
235
|
string no_http = StringUtil::Replace(url, "http://", "");
|
223
236
|
|
@@ -227,7 +240,7 @@ void ExtensionHelper::InstallExtensionInternal(DBConfig &config, ClientConfig *c
|
|
227
240
|
}
|
228
241
|
|
229
242
|
// Special case to install extension from a local file, useful for testing
|
230
|
-
if (!StringUtil::Contains(
|
243
|
+
if (!StringUtil::Contains(url_template, "http://")) {
|
231
244
|
string file = fs.ConvertSeparators(url);
|
232
245
|
if (!fs.FileExists(file)) {
|
233
246
|
// check for non-gzipped variant
|
@@ -58,7 +58,8 @@ static void ComputeSHA256FileSegment(FileHandle *handle, const idx_t start, cons
|
|
58
58
|
#endif
|
59
59
|
|
60
60
|
bool ExtensionHelper::TryInitialLoad(DBConfig &config, FileSystem &fs, const string &extension,
|
61
|
-
ExtensionInitResult &result, string &error
|
61
|
+
ExtensionInitResult &result, string &error,
|
62
|
+
optional_ptr<const ClientConfig> client_config) {
|
62
63
|
#ifdef DUCKDB_DISABLE_EXTENSION_LOAD
|
63
64
|
throw PermissionException("Loading external extensions is disabled through a compile time flag");
|
64
65
|
#else
|
@@ -69,6 +70,30 @@ bool ExtensionHelper::TryInitialLoad(DBConfig &config, FileSystem &fs, const str
|
|
69
70
|
|
70
71
|
// shorthand case
|
71
72
|
if (!ExtensionHelper::IsFullPath(extension)) {
|
73
|
+
#ifdef WASM_LOADABLE_EXTENSIONS
|
74
|
+
string url_template = ExtensionUrlTemplate(client_config, "");
|
75
|
+
string url = ExtensionFinalizeUrlTemplate(url_template, extension_name);
|
76
|
+
|
77
|
+
char *str = (char *)EM_ASM_PTR(
|
78
|
+
{
|
79
|
+
var jsString = ((typeof runtime == = 'object') && runtime &&
|
80
|
+
(typeof runtime.whereToLoad == = 'function') && runtime.whereToLoad)
|
81
|
+
? runtime.whereToLoad(UTF8ToString($0))
|
82
|
+
: (UTF8ToString($1));
|
83
|
+
var lengthBytes = lengthBytesUTF8(jsString) + 1;
|
84
|
+
// 'jsString.length' would return the length of the string as UTF-16
|
85
|
+
// units, but Emscripten C strings operate as UTF-8.
|
86
|
+
var stringOnWasmHeap = _malloc(lengthBytes);
|
87
|
+
stringToUTF8(jsString, stringOnWasmHeap, lengthBytes);
|
88
|
+
return stringOnWasmHeap;
|
89
|
+
},
|
90
|
+
filename.c_str(), url.c_str());
|
91
|
+
std::string address(str);
|
92
|
+
free(str);
|
93
|
+
|
94
|
+
filename = address;
|
95
|
+
#else
|
96
|
+
|
72
97
|
string local_path =
|
73
98
|
!config.options.extension_directory.empty() ? config.options.extension_directory : fs.GetHomeDirectory();
|
74
99
|
|
@@ -82,6 +107,7 @@ bool ExtensionHelper::TryInitialLoad(DBConfig &config, FileSystem &fs, const str
|
|
82
107
|
}
|
83
108
|
string extension_name = ApplyExtensionAlias(extension);
|
84
109
|
filename = fs.JoinPath(local_path, extension_name + ".duckdb_extension");
|
110
|
+
#endif
|
85
111
|
}
|
86
112
|
if (!fs.FileExists(filename)) {
|
87
113
|
string message;
|
@@ -216,17 +242,18 @@ bool ExtensionHelper::TryInitialLoad(DBConfig &config, FileSystem &fs, const str
|
|
216
242
|
#endif
|
217
243
|
}
|
218
244
|
|
219
|
-
ExtensionInitResult ExtensionHelper::InitialLoad(DBConfig &config, FileSystem &fs, const string &extension
|
245
|
+
ExtensionInitResult ExtensionHelper::InitialLoad(DBConfig &config, FileSystem &fs, const string &extension,
|
246
|
+
optional_ptr<const ClientConfig> client_config) {
|
220
247
|
string error;
|
221
248
|
ExtensionInitResult result;
|
222
|
-
if (!TryInitialLoad(config, fs, extension, result, error)) {
|
249
|
+
if (!TryInitialLoad(config, fs, extension, result, error, client_config)) {
|
223
250
|
if (!ExtensionHelper::AllowAutoInstall(extension)) {
|
224
251
|
throw IOException(error);
|
225
252
|
}
|
226
253
|
// the extension load failed - try installing the extension
|
227
254
|
ExtensionHelper::InstallExtension(config, fs, extension, false);
|
228
255
|
// try loading again
|
229
|
-
if (!TryInitialLoad(config, fs, extension, result, error)) {
|
256
|
+
if (!TryInitialLoad(config, fs, extension, result, error, client_config)) {
|
230
257
|
throw IOException(error);
|
231
258
|
}
|
232
259
|
}
|
@@ -254,14 +281,15 @@ string ExtensionHelper::GetExtensionName(const string &original_name) {
|
|
254
281
|
return ExtensionHelper::ApplyExtensionAlias(splits.front());
|
255
282
|
}
|
256
283
|
|
257
|
-
void ExtensionHelper::LoadExternalExtension(DatabaseInstance &db, FileSystem &fs, const string &extension
|
284
|
+
void ExtensionHelper::LoadExternalExtension(DatabaseInstance &db, FileSystem &fs, const string &extension,
|
285
|
+
optional_ptr<const ClientConfig> client_config) {
|
258
286
|
if (db.ExtensionIsLoaded(extension)) {
|
259
287
|
return;
|
260
288
|
}
|
261
289
|
#ifdef DUCKDB_DISABLE_EXTENSION_LOAD
|
262
290
|
throw PermissionException("Loading external extensions is disabled through a compile time flag");
|
263
291
|
#else
|
264
|
-
auto res = InitialLoad(DBConfig::GetConfig(db), fs, extension);
|
292
|
+
auto res = InitialLoad(DBConfig::GetConfig(db), fs, extension, client_config);
|
265
293
|
auto init_fun_name = res.basename + "_init";
|
266
294
|
|
267
295
|
ext_init_fun_t init_fun;
|
@@ -279,7 +307,8 @@ void ExtensionHelper::LoadExternalExtension(DatabaseInstance &db, FileSystem &fs
|
|
279
307
|
}
|
280
308
|
|
281
309
|
void ExtensionHelper::LoadExternalExtension(ClientContext &context, const string &extension) {
|
282
|
-
LoadExternalExtension(DatabaseInstance::GetDatabase(context), FileSystem::GetFileSystem(context), extension
|
310
|
+
LoadExternalExtension(DatabaseInstance::GetDatabase(context), FileSystem::GetFileSystem(context), extension,
|
311
|
+
&ClientConfig::GetConfig(context));
|
283
312
|
}
|
284
313
|
|
285
314
|
string ExtensionHelper::ExtractExtensionPrefixFromPath(const string &path) {
|