mirror of
https://github.com/neondatabase/neon.git
synced 2026-05-15 12:10:37 +00:00
Compare commits
13 Commits
jcsp/rfc-e
...
alexk/add-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4991c77e5 | ||
|
|
fa2657da9e | ||
|
|
76a4654424 | ||
|
|
aadbdf19d6 | ||
|
|
7ab475520d | ||
|
|
0654c03d18 | ||
|
|
a6a42c58c3 | ||
|
|
b6c010035f | ||
|
|
1ffd697090 | ||
|
|
d6a4896070 | ||
|
|
3e84dfb620 | ||
|
|
1ae0ab2554 | ||
|
|
405624294e |
@@ -34,11 +34,11 @@ RUN case $DEBIAN_VERSION in \
|
||||
echo "Unknown Debian version ${DEBIAN_VERSION}" && exit 1 \
|
||||
;; \
|
||||
esac && \
|
||||
apt update && \
|
||||
apt update && \
|
||||
apt install --no-install-recommends --no-install-suggests -y \
|
||||
ninja-build git autoconf automake libtool build-essential bison flex libreadline-dev \
|
||||
zlib1g-dev libxml2-dev libcurl4-openssl-dev libossp-uuid-dev wget ca-certificates pkg-config libssl-dev \
|
||||
libicu-dev libxslt1-dev liblz4-dev libzstd-dev zstd \
|
||||
libicu-dev libxslt1-dev liblz4-dev libzstd-dev zstd g++ \
|
||||
$VERSION_INSTALLS \
|
||||
&& apt clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -1107,6 +1107,46 @@ RUN wget https://github.com/Mooncake-Labs/pg_mooncake/releases/download/v0.1.0/p
|
||||
make install -j $(getconf _NPROCESSORS_ONLN) && \
|
||||
echo 'trusted = true' >> /usr/local/pgsql/share/extension/pg_mooncake.control
|
||||
|
||||
#########################################################################################
|
||||
#
|
||||
# Layer "pg-duckdb-pg-build"
|
||||
# compile pg_duckdb extension
|
||||
#
|
||||
#########################################################################################
|
||||
|
||||
FROM build-deps AS pg-duckdb-pg-build
|
||||
ARG PG_VERSION
|
||||
COPY --from=pg-build /usr/local/pgsql/ /usr/local/pgsql/
|
||||
COPY compute/patches/duckdb-v1-1-3.patch /duckdb-v1-1-3.patch
|
||||
COPY compute/patches/pg_duckdb-0-2-0.patch /pg_duckdb-0-2-0.patch
|
||||
|
||||
ENV PATH="/usr/local/pgsql/bin/:$PATH"
|
||||
|
||||
|
||||
# pg_duckdb build requires source dir to be a git repo to get submodules
|
||||
# allow neon_superuser to execute some functions that in pg_duckdb are available to superuser only
|
||||
# cache management functions duckdb.cache(), duckdb.cache_info(), duckdb.cache_delete()
|
||||
# extension management function duckdb.install_extension()
|
||||
# for debugging purposes raw query and reset ddb duckdb.raw_query(), duckdb.recycle_ddb()
|
||||
RUN git clone --depth 1 --branch v0.2.0 https://github.com/duckdb/pg_duckdb.git pg_duckdb-src && \
|
||||
cd pg_duckdb-src && \
|
||||
git submodule update --init --recursive && \
|
||||
cd third_party/duckdb && \
|
||||
patch -p1 < /duckdb-v1-1-3.patch && \
|
||||
cd ../.. && \
|
||||
patch -p1 < /pg_duckdb-0-2-0.patch && \
|
||||
make install -j $(getconf _NPROCESSORS_ONLN) && \
|
||||
echo 'trusted = true' >> /usr/local/pgsql/share/extension/pg_duckdb.control && \
|
||||
file=/usr/local/pgsql/share/extension/pg_duckdb--0.1.0--0.2.0.sql && \
|
||||
echo 'GRANT ALL ON FUNCTION duckdb.cache(TEXT, TEXT) TO neon_superuser;' >> $file && \
|
||||
echo 'GRANT ALL ON FUNCTION duckdb.cache_info() TO neon_superuser;' >> $file && \
|
||||
echo 'GRANT ALL ON FUNCTION duckdb.cache_delete(cache_key TEXT) TO neon_superuser;' >> $file && \
|
||||
echo 'GRANT ALL ON FUNCTION duckdb.install_extension(TEXT) TO neon_superuser;' >> $file && \
|
||||
echo 'GRANT ALL ON FUNCTION duckdb.raw_query(TEXT) TO neon_superuser;' >> $file && \
|
||||
echo 'GRANT ALL ON PROCEDURE duckdb.recycle_ddb() TO neon_superuser;' >> $file && \
|
||||
echo 'GRANT ALL ON TABLE duckdb.extensions TO neon_superuser;' >> $file && \
|
||||
echo 'GRANT ALL ON SEQUENCE duckdb.extensions_table_seq TO neon_superuser;' >> $file
|
||||
|
||||
#########################################################################################
|
||||
#
|
||||
# Layer "pg_repack"
|
||||
@@ -1169,6 +1209,7 @@ COPY --from=pg-ivm-build /usr/local/pgsql/ /usr/local/pgsql/
|
||||
COPY --from=pg-partman-build /usr/local/pgsql/ /usr/local/pgsql/
|
||||
COPY --from=pg-mooncake-build /usr/local/pgsql/ /usr/local/pgsql/
|
||||
COPY --from=pg-repack-build /usr/local/pgsql/ /usr/local/pgsql/
|
||||
COPY --from=pg-duckdb-pg-build /usr/local/pgsql/ /usr/local/pgsql/
|
||||
COPY pgxn/ pgxn/
|
||||
|
||||
RUN make -j $(getconf _NPROCESSORS_ONLN) \
|
||||
|
||||
122
compute/patches/duckdb-v1-1-3.patch
Normal file
122
compute/patches/duckdb-v1-1-3.patch
Normal file
@@ -0,0 +1,122 @@
|
||||
diff --git a/src/common/virtual_file_system.cpp b/src/common/virtual_file_system.cpp
|
||||
index 74892a4e05..60e9e7af88 100644
|
||||
--- a/src/common/virtual_file_system.cpp
|
||||
+++ b/src/common/virtual_file_system.cpp
|
||||
@@ -173,7 +173,9 @@ void VirtualFileSystem::SetDisabledFileSystems(const vector<string> &names) {
|
||||
|
||||
FileSystem &VirtualFileSystem::FindFileSystem(const string &path) {
|
||||
auto &fs = FindFileSystemInternal(path);
|
||||
- if (!disabled_file_systems.empty() && disabled_file_systems.find(fs.GetName()) != disabled_file_systems.end()) {
|
||||
+ // we allow LocalFileSystem access to duckdb itself (by specifiying trustedContext=true)
|
||||
+ // but not to duckdb users if disabled_file_systems='LocalFileSystem'
|
||||
+ if (!isTrustedContext && !disabled_file_systems.empty() && disabled_file_systems.find(fs.GetName()) != disabled_file_systems.end()) {
|
||||
throw PermissionException("File system %s has been disabled by configuration", fs.GetName());
|
||||
}
|
||||
return fs;
|
||||
diff --git a/src/include/duckdb/common/file_system.hpp b/src/include/duckdb/common/file_system.hpp
|
||||
index 0b83c4f393..58d70889cf 100644
|
||||
--- a/src/include/duckdb/common/file_system.hpp
|
||||
+++ b/src/include/duckdb/common/file_system.hpp
|
||||
@@ -256,6 +256,30 @@ public:
|
||||
DynamicCastCheck<TARGET>(this);
|
||||
return reinterpret_cast<const TARGET &>(*this);
|
||||
}
|
||||
+public:
|
||||
+ DUCKDB_API virtual void setTrusted(){
|
||||
+ this->isTrustedContext = true;
|
||||
+ }
|
||||
+ DUCKDB_API virtual void setUntrusted(){
|
||||
+ this->isTrustedContext = false;
|
||||
+ }
|
||||
+
|
||||
+public:
|
||||
+ class TrustedContext {
|
||||
+ public:
|
||||
+ TrustedContext(FileSystem &fs) : fileSystem(fs) {
|
||||
+ fileSystem.setTrusted();
|
||||
+ }
|
||||
+ ~TrustedContext() {
|
||||
+ fileSystem.setUntrusted();
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
+ FileSystem &fileSystem;
|
||||
+ };
|
||||
+
|
||||
+protected:
|
||||
+ bool isTrustedContext = false;
|
||||
};
|
||||
|
||||
} // namespace duckdb
|
||||
diff --git a/src/include/duckdb/common/opener_file_system.hpp b/src/include/duckdb/common/opener_file_system.hpp
|
||||
index 2d35512b21..d1597173ee 100644
|
||||
--- a/src/include/duckdb/common/opener_file_system.hpp
|
||||
+++ b/src/include/duckdb/common/opener_file_system.hpp
|
||||
@@ -143,6 +143,18 @@ public:
|
||||
vector<string> ListSubSystems() override {
|
||||
return GetFileSystem().ListSubSystems();
|
||||
}
|
||||
+
|
||||
+private:
|
||||
+
|
||||
+ virtual void setTrusted() override {
|
||||
+ this->isTrustedContext = true;
|
||||
+ GetFileSystem().setTrusted();
|
||||
+ }
|
||||
+
|
||||
+ virtual void setUntrusted() override {
|
||||
+ this->isTrustedContext = false;
|
||||
+ GetFileSystem().setUntrusted();
|
||||
+ }
|
||||
};
|
||||
|
||||
} // namespace duckdb
|
||||
diff --git a/src/main/extension/extension_install.cpp b/src/main/extension/extension_install.cpp
|
||||
index 1258d95ead..def1ba71cb 100644
|
||||
--- a/src/main/extension/extension_install.cpp
|
||||
+++ b/src/main/extension/extension_install.cpp
|
||||
@@ -57,6 +57,7 @@ const vector<string> ExtensionHelper::PathComponents() {
|
||||
}
|
||||
|
||||
duckdb::string ExtensionHelper::DefaultExtensionFolder(FileSystem &fs) {
|
||||
+ FileSystem::TrustedContext trusted(fs);
|
||||
string home_directory = fs.GetHomeDirectory();
|
||||
// exception if the home directory does not exist, don't create whatever we think is home
|
||||
if (!fs.DirectoryExists(home_directory)) {
|
||||
@@ -84,6 +85,7 @@ string ExtensionHelper::ExtensionDirectory(DatabaseInstance &db, FileSystem &fs)
|
||||
extension_directory = DefaultExtensionFolder(fs);
|
||||
}
|
||||
{
|
||||
+ FileSystem::TrustedContext trusted(fs);
|
||||
extension_directory = fs.ConvertSeparators(extension_directory);
|
||||
// expand ~ in extension directory
|
||||
extension_directory = fs.ExpandPath(extension_directory);
|
||||
@@ -107,6 +109,7 @@ string ExtensionHelper::ExtensionDirectory(DatabaseInstance &db, FileSystem &fs)
|
||||
|
||||
auto path_components = PathComponents();
|
||||
for (auto &path_ele : path_components) {
|
||||
+ FileSystem::TrustedContext trusted(fs);
|
||||
extension_directory = fs.JoinPath(extension_directory, path_ele);
|
||||
if (!fs.DirectoryExists(extension_directory)) {
|
||||
fs.CreateDirectory(extension_directory);
|
||||
@@ -538,7 +541,7 @@ ExtensionHelper::InstallExtensionInternal(DatabaseInstance &db, FileSystem &fs,
|
||||
if (!db.config.options.enable_external_access) {
|
||||
throw PermissionException("Installing extensions is disabled through configuration");
|
||||
}
|
||||
-
|
||||
+ FileSystem::TrustedContext trusted(fs);
|
||||
auto extension_name = ApplyExtensionAlias(fs.ExtractBaseName(extension));
|
||||
string local_extension_path = fs.JoinPath(local_path, extension_name + ".duckdb_extension");
|
||||
string temp_path = local_extension_path + ".tmp-" + UUID::ToString(UUID::GenerateRandomUUID());
|
||||
diff --git a/src/main/extension/extension_load.cpp b/src/main/extension/extension_load.cpp
|
||||
index b0282a7103..c2765f97c6 100644
|
||||
--- a/src/main/extension/extension_load.cpp
|
||||
+++ b/src/main/extension/extension_load.cpp
|
||||
@@ -293,6 +293,7 @@ bool ExtensionHelper::TryInitialLoad(DatabaseInstance &db, FileSystem &fs, const
|
||||
if (!db.config.options.enable_external_access) {
|
||||
throw PermissionException("Loading external extensions is disabled through configuration");
|
||||
}
|
||||
+ FileSystem::TrustedContext trusted(fs);
|
||||
auto filename = fs.ConvertSeparators(extension);
|
||||
|
||||
bool direct_load;
|
||||
61
compute/patches/pg_duckdb-0-2-0.patch
Normal file
61
compute/patches/pg_duckdb-0-2-0.patch
Normal file
@@ -0,0 +1,61 @@
|
||||
diff --git a/third_party/cached_httpfs/http_file_cache.cpp b/third_party/cached_httpfs/http_file_cache.cpp
|
||||
index 813db57..c6e4c3a 100644
|
||||
--- a/third_party/cached_httpfs/http_file_cache.cpp
|
||||
+++ b/third_party/cached_httpfs/http_file_cache.cpp
|
||||
@@ -4,20 +4,22 @@ namespace duckdb {
|
||||
|
||||
CachedFile::CachedFile(const string &cache_dir, FileSystem &fs, const string &key, bool cache_file) : cache_directory(cache_dir), fs(fs) {
|
||||
file_name = cache_dir + "/" + key;
|
||||
-
|
||||
+ FileSystem::TrustedContext trusted1(fs);
|
||||
GetDirectoryCacheLock(cache_dir);
|
||||
|
||||
FileOpenFlags flags =
|
||||
FileFlags::FILE_FLAGS_READ | FileFlags::FILE_FLAGS_NULL_IF_NOT_EXISTS | FileLockType::READ_LOCK;
|
||||
+ FileSystem::TrustedContext trusted2(fs);
|
||||
handle = fs.OpenFile(file_name, flags);
|
||||
if (handle) {
|
||||
initialized = true;
|
||||
size = handle->GetFileSize();
|
||||
} else if (cache_file) {
|
||||
flags = FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE | FileLockType::WRITE_LOCK;
|
||||
+ FileSystem::TrustedContext trusted3(fs);
|
||||
handle = fs.OpenFile(file_name, flags);
|
||||
}
|
||||
-
|
||||
+ FileSystem::TrustedContext trusted4(fs);
|
||||
ReleaseDirectoryCacheLock();
|
||||
}
|
||||
|
||||
@@ -30,6 +32,7 @@ void CachedFile::GetDirectoryCacheLock(const string &cache_dir) {
|
||||
FileOpenFlags flags = FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE |
|
||||
FileFlags::FILE_FLAGS_EXCLUSIVE_CREATE | FileFlags::FILE_FLAGS_NULL_IF_EXISTS |
|
||||
FileLockType::WRITE_LOCK;
|
||||
+ FileSystem::TrustedContext trusted(fs);
|
||||
directory_lock_handle = fs.OpenFile(lock_file, flags);
|
||||
if (directory_lock_handle == nullptr) {
|
||||
flags = FileFlags::FILE_FLAGS_WRITE | FileLockType::WRITE_LOCK;
|
||||
@@ -52,6 +55,7 @@ void CachedFileHandle::WriteMetadata(const string &cache_key, const string &remo
|
||||
D_ASSERT(!file->initialized);
|
||||
string metadata_file_name = file->cache_directory + "/" + cache_key + ".meta";
|
||||
FileOpenFlags flags = FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE | FileLockType::WRITE_LOCK;
|
||||
+ FileSystem::TrustedContext trusted(file->fs);
|
||||
auto handle = file->fs.OpenFile(metadata_file_name, flags);
|
||||
auto cached_file_timestamp = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
string metadata_info = cache_key + "," + remote_path + "," + std::to_string(total_size) + "," + std::to_string(cached_file_timestamp);
|
||||
@@ -66,6 +70,7 @@ void CachedFileHandle::SetInitialized(idx_t total_size) {
|
||||
file->initialized = true;
|
||||
file->handle->Close();
|
||||
FileOpenFlags flags = FileFlags::FILE_FLAGS_READ | FileLockType::READ_LOCK;
|
||||
+ FileSystem::TrustedContext trusted(file->fs);
|
||||
file->handle = file->fs.OpenFile(file->file_name, flags);
|
||||
}
|
||||
|
||||
@@ -93,6 +98,7 @@ void CachedFileHandle::Read(void *buffer, idx_t length, idx_t offset) {
|
||||
//! Get cache entry, create if not exists only if caching is enabled
|
||||
shared_ptr<CachedFile> HTTPFileCache::GetCachedFile(const string &cache_dir, const string &key, bool cache_file) {
|
||||
lock_guard<mutex> lock(cached_files_mutex);
|
||||
+ FileSystem::TrustedContext trusted(db->GetFileSystem());
|
||||
auto it = cached_files.find(key);
|
||||
if (it != cached_files.end()) {
|
||||
return it->second;
|
||||
Reference in New Issue
Block a user