Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/duckdb/extension/icu/third_party/icu/common/putil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1090,9 +1090,15 @@ uprv_tzname(int n)
if (tzid[0] == ':') {
tzid++;
}
/* This might be a good Olson ID. */
skipZoneIDPrefix(&tzid);
return tzid;
#if defined(TZDEFAULT)
if (uprv_strcmp(tzid, TZDEFAULT) != 0) {
#endif
/* This might be a good Olson ID. */
skipZoneIDPrefix(&tzid);
return tzid;
#if defined(TZDEFAULT)
}
#endif
}
/* else U_TZNAME will give a better result. */
#endif
Expand Down
8 changes: 4 additions & 4 deletions src/duckdb/src/common/adbc/adbc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -659,12 +659,12 @@ AdbcStatusCode Ingest(duckdb_connection connection, const char *table_name, cons
std::ostringstream create_table;
create_table << "CREATE TABLE ";
if (schema) {
create_table << schema << ".";
create_table << duckdb::KeywordHelper::WriteOptionallyQuoted(schema) << ".";
}
create_table << table_name << " (";
create_table << duckdb::KeywordHelper::WriteOptionallyQuoted(table_name) << " (";
for (idx_t i = 0; i < types.size(); i++) {
create_table << names[i] << " ";
create_table << types[i].ToString();
create_table << duckdb::KeywordHelper::WriteOptionallyQuoted(names[i]);
create_table << " " << types[i].ToString();
if (i + 1 < types.size()) {
create_table << ", ";
}
Expand Down
6 changes: 3 additions & 3 deletions src/duckdb/src/function/table/version/pragma_version.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef DUCKDB_PATCH_VERSION
#define DUCKDB_PATCH_VERSION "2-dev99"
#define DUCKDB_PATCH_VERSION "2-dev105"
#endif
#ifndef DUCKDB_MINOR_VERSION
#define DUCKDB_MINOR_VERSION 4
Expand All @@ -8,10 +8,10 @@
#define DUCKDB_MAJOR_VERSION 1
#endif
#ifndef DUCKDB_VERSION
#define DUCKDB_VERSION "v1.4.2-dev99"
#define DUCKDB_VERSION "v1.4.2-dev105"
#endif
#ifndef DUCKDB_SOURCE_ID
#define DUCKDB_SOURCE_ID "62a68d6f7b"
#define DUCKDB_SOURCE_ID "b6dcebf822"
#endif
#include "duckdb/function/table/system_functions.hpp"
#include "duckdb/main/database.hpp"
Expand Down
11 changes: 9 additions & 2 deletions src/duckdb/src/include/duckdb/storage/block_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class ClientContext;
class DatabaseInstance;
class MetadataManager;

enum class ConvertToPersistentMode { DESTRUCTIVE, THREAD_SAFE };

//! BlockManager is an abstract representation to manage blocks on DuckDB. When writing or reading blocks, the
//! BlockManager creates and accesses blocks. The concrete types implement specific block storage strategies.
class BlockManager {
Expand Down Expand Up @@ -91,10 +93,15 @@ class BlockManager {
//! Register a block with the given block id in the base file
shared_ptr<BlockHandle> RegisterBlock(block_id_t block_id);
//! Convert an existing in-memory buffer into a persistent disk-backed block
//! If mode is set to destructive (default) - the old_block will be destroyed as part of this method
//! This can only be safely used when there is no other (lingering) usage of old_block
//! If there is concurrent usage of the block elsewhere - use the THREAD_SAFE mode which creates an extra copy
shared_ptr<BlockHandle> ConvertToPersistent(QueryContext context, block_id_t block_id,
shared_ptr<BlockHandle> old_block, BufferHandle old_handle);
shared_ptr<BlockHandle> old_block, BufferHandle old_handle,
ConvertToPersistentMode mode = ConvertToPersistentMode::DESTRUCTIVE);
shared_ptr<BlockHandle> ConvertToPersistent(QueryContext context, block_id_t block_id,
shared_ptr<BlockHandle> old_block);
shared_ptr<BlockHandle> old_block,
ConvertToPersistentMode mode = ConvertToPersistentMode::DESTRUCTIVE);

void UnregisterBlock(BlockHandle &block);
//! UnregisterBlock, only accepts non-temporary block ids
Expand Down
26 changes: 20 additions & 6 deletions src/duckdb/src/storage/buffer/block_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,32 @@ shared_ptr<BlockHandle> BlockManager::RegisterBlock(block_id_t block_id) {
}

shared_ptr<BlockHandle> BlockManager::ConvertToPersistent(QueryContext context, block_id_t block_id,
shared_ptr<BlockHandle> old_block, BufferHandle old_handle) {
shared_ptr<BlockHandle> old_block, BufferHandle old_handle,
ConvertToPersistentMode mode) {
// register a block with the new block id
auto new_block = RegisterBlock(block_id);
D_ASSERT(new_block->GetState() == BlockState::BLOCK_UNLOADED);
D_ASSERT(new_block->Readers() == 0);

if (mode == ConvertToPersistentMode::THREAD_SAFE) {
// safe mode - create a copy of the old block and operate on that
// this ensures we don't modify the old block - which allows other concurrent operations on the old block to
// continue
auto old_block_copy = buffer_manager.AllocateMemory(old_block->GetMemoryTag(), this, false);
auto copy_pin = buffer_manager.Pin(old_block_copy);
memcpy(copy_pin.Ptr(), old_handle.Ptr(), GetBlockSize());
old_block = std::move(old_block_copy);
old_handle = std::move(copy_pin);
}

auto lock = old_block->GetLock();
D_ASSERT(old_block->GetState() == BlockState::BLOCK_LOADED);
D_ASSERT(old_block->GetBuffer(lock));
if (old_block->Readers() > 1) {
throw InternalException("BlockManager::ConvertToPersistent - cannot be called for block %d as old_block has "
"multiple readers active",
block_id);
throw InternalException(
"BlockManager::ConvertToPersistent in destructive mode - cannot be called for block %d as old_block has "
"multiple readers active",
block_id);
}

// Temp buffers can be larger than the storage block size.
Expand Down Expand Up @@ -76,10 +89,11 @@ shared_ptr<BlockHandle> BlockManager::ConvertToPersistent(QueryContext context,
}

shared_ptr<BlockHandle> BlockManager::ConvertToPersistent(QueryContext context, block_id_t block_id,
shared_ptr<BlockHandle> old_block) {
shared_ptr<BlockHandle> old_block,
ConvertToPersistentMode mode) {
// pin the old block to ensure we have it loaded in memory
auto handle = buffer_manager.Pin(old_block);
return ConvertToPersistent(context, block_id, std::move(old_block), std::move(handle));
return ConvertToPersistent(context, block_id, std::move(old_block), std::move(handle), mode);
}

void BlockManager::UnregisterBlock(block_id_t id) {
Expand Down
13 changes: 8 additions & 5 deletions src/duckdb/src/storage/metadata/metadata_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,15 +272,18 @@ void MetadataManager::Flush() {
}
continue;
}
auto handle = buffer_manager.Pin(block.block);
auto block_handle = block.block;
auto handle = buffer_manager.Pin(block_handle);
// zero-initialize the few leftover bytes
memset(handle.Ptr() + total_metadata_size, 0, block_manager.GetBlockSize() - total_metadata_size);
D_ASSERT(kv.first == block.block_id);
if (block.block->BlockId() >= MAXIMUM_BLOCK) {
auto new_block =
block_manager.ConvertToPersistent(QueryContext(), kv.first, block.block, std::move(handle));

if (block_handle->BlockId() >= MAXIMUM_BLOCK) {
// Convert the temporary block to a persistent block.
// we cannot use ConvertToPersistent as another thread might still be reading the block
// so we use the safe version of ConvertToPersistent
auto new_block = block_manager.ConvertToPersistent(QueryContext(), kv.first, std::move(block_handle),
std::move(handle), ConvertToPersistentMode::THREAD_SAFE);

guard.lock();
block.block = std::move(new_block);
guard.unlock();
Expand Down
4 changes: 3 additions & 1 deletion src/duckdb/src/storage/standard_buffer_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,8 +542,10 @@ unique_ptr<FileBuffer> StandardBufferManager::ReadTemporaryBuffer(QueryContext c
BlockHandle &block,
unique_ptr<FileBuffer> reusable_buffer) {
D_ASSERT(!temporary_directory.path.empty());
D_ASSERT(temporary_directory.handle.get());
auto id = block.BlockId();
if (!temporary_directory.handle) {
throw InternalException("ReadTemporaryBuffer called but temporary directory has not been instantiated yet");
}
if (temporary_directory.handle->GetTempFile().HasTemporaryBuffer(id)) {
// This is a block that was offloaded to a regular .tmp file, the file contains blocks of a fixed size
return temporary_directory.handle->GetTempFile().ReadTemporaryBuffer(context, id, std::move(reusable_buffer));
Expand Down