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
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 "0-dev4109"
#define DUCKDB_PATCH_VERSION "0-dev4124"
#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.0-dev4109"
#define DUCKDB_VERSION "v1.4.0-dev4124"
#endif
#ifndef DUCKDB_SOURCE_ID
#define DUCKDB_SOURCE_ID "b3edbac851"
#define DUCKDB_SOURCE_ID "b8a06e4a22"
#endif
#include "duckdb/function/table/system_functions.hpp"
#include "duckdb/main/database.hpp"
Expand Down
2 changes: 2 additions & 0 deletions src/duckdb/src/include/duckdb/planner/expression_binder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ class ExpressionBinder {

BindResult BindUnsupportedExpression(ParsedExpression &expr, idx_t depth, const string &message);

optional_ptr<CatalogEntry> BindAndQualifyFunction(FunctionExpression &function, bool allow_throw);

protected:
virtual BindResult BindGroupingFunction(OperatorExpression &op, idx_t depth);
virtual BindResult BindFunction(FunctionExpression &expr, ScalarFunctionCatalogEntry &function, idx_t depth);
Expand Down
2 changes: 1 addition & 1 deletion src/duckdb/src/include/duckdb/storage/table/row_group.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class RowGroup : public SegmentBase<RowGroup> {
const vector<PhysicalIndex> &column_ids);
//! Update a single column; corresponds to DataTable::UpdateColumn
//! This method should only be called from the WAL
void UpdateColumn(TransactionData transaction, DataChunk &updates, Vector &row_ids,
void UpdateColumn(TransactionData transaction, DataChunk &updates, Vector &row_ids, idx_t offset, idx_t count,
const vector<column_t> &column_path);

void MergeStatistics(idx_t column_idx, const BaseStatistics &other);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ class RowGroupCollection {
private:
bool IsEmpty(SegmentLock &) const;

optional_ptr<RowGroup> NextUpdateRowGroup(row_t *ids, idx_t &pos, idx_t count) const;

private:
//! BlockManager
BlockManager &block_manager;
Expand Down
14 changes: 7 additions & 7 deletions src/duckdb/src/main/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,10 @@ idx_t DBConfig::GetSystemMaxThreads(FileSystem &fs) {
}

idx_t DBConfig::GetSystemAvailableMemory(FileSystem &fs) {
// System memory detection
auto memory = FileSystem::GetAvailableMemory();
auto available_memory = memory.IsValid() ? memory.GetIndex() : DBConfigOptions().maximum_memory;

#ifdef __linux__
// Check SLURM environment variables first
const char *slurm_mem_per_node = getenv("SLURM_MEM_PER_NODE");
Expand All @@ -560,16 +564,12 @@ idx_t DBConfig::GetSystemAvailableMemory(FileSystem &fs) {
// Check cgroup memory limit
auto cgroup_memory_limit = CGroups::GetMemoryLimit(fs);
if (cgroup_memory_limit.IsValid()) {
return cgroup_memory_limit.GetIndex();
auto cgroup_memory_limit_value = cgroup_memory_limit.GetIndex();
return std::min(cgroup_memory_limit_value, available_memory);
}
#endif

// System memory detection
auto memory = FileSystem::GetAvailableMemory();
if (!memory.IsValid()) {
return DBConfigOptions().maximum_memory;
}
return memory.GetIndex();
return available_memory;
}

idx_t DBConfig::ParseMemoryLimit(const string &arg) {
Expand Down
14 changes: 12 additions & 2 deletions src/duckdb/src/main/database_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,18 @@ shared_ptr<AttachedDatabase> DatabaseManager::AttachDatabase(ClientContext &cont
AttachOptions &options) {
auto &config = DBConfig::GetConfig(context);
if (options.db_type.empty() || StringUtil::CIEquals(options.db_type, "duckdb")) {
if (InsertDatabasePath(info, options) == InsertDatabasePathResult::ALREADY_EXISTS) {
return nullptr;
while (InsertDatabasePath(info, options) == InsertDatabasePathResult::ALREADY_EXISTS) {
// database with this name and path already exists
// ... but it might not be done attaching yet!
// verify the database has actually finished attaching prior to returning
lock_guard<mutex> guard(databases_lock);
if (databases.find(info.name) != databases.end()) {
// database ACTUALLY exists - return
return nullptr;
}
if (context.interrupted) {
throw InterruptException();
}
}
}
GetDatabaseType(context, info, config, options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ void ExpressionBinder::QualifyColumnNames(unique_ptr<ParsedExpression> &expr,
case ExpressionType::FUNCTION: {
// Special-handling for lambdas, which are inside function expressions.
auto &function = expr->Cast<FunctionExpression>();
if (!IsUnnestFunction(function.function_name)) {
BindAndQualifyFunction(function, false);
}
if (function.IsLambdaFunction()) {
return QualifyColumnNamesInLambda(function, lambda_params);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ BindResult ExpressionBinder::TryBindLambdaOrJson(FunctionExpression &function, i
json_bind_result.error.RawMessage());
}

BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t depth,
unique_ptr<ParsedExpression> &expr_ptr) {
optional_ptr<CatalogEntry> ExpressionBinder::BindAndQualifyFunction(FunctionExpression &function, bool allow_throw) {
D_ASSERT(!IsUnnestFunction(function.function_name));
// lookup the function in the catalog
QueryErrorContext error_context(function.GetQueryLocation());
binder.BindSchemaOrCatalog(function.catalog, function.schema);
Expand All @@ -82,6 +82,9 @@ BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t
auto table_func =
GetCatalogEntry(function.catalog, function.schema, table_function_lookup, OnEntryNotFound::RETURN_NULL);
if (table_func) {
if (!allow_throw) {
return func;
}
throw BinderException(function,
"Function \"%s\" is a table function but it was used as a scalar function. This "
"function has to be called in a FROM clause (similar to a table).",
Expand All @@ -105,6 +108,9 @@ BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t
if (error.HasError()) {
// could not find the column - try to qualify the alias
if (!QualifyColumnAlias(*colref)) {
if (!allow_throw) {
return func;
}
// no alias found either - throw
error.Throw();
}
Expand All @@ -118,11 +124,19 @@ BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t
}
// rebind the function
if (!func) {
func =
GetCatalogEntry(function.catalog, function.schema, function_lookup, OnEntryNotFound::THROW_EXCEPTION);
const auto on_entry_not_found =
allow_throw ? OnEntryNotFound::THROW_EXCEPTION : OnEntryNotFound::RETURN_NULL;
func = GetCatalogEntry(function.catalog, function.schema, function_lookup, on_entry_not_found);
}
}

return func;
}

BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t depth,
unique_ptr<ParsedExpression> &expr_ptr) {
auto func = BindAndQualifyFunction(function, true);

if (func->type != CatalogType::AGGREGATE_FUNCTION_ENTRY &&
(function.distinct || function.filter || !function.order_bys->orders.empty())) {
throw InvalidInputException("Function \"%s\" is a %s. \"DISTINCT\", \"FILTER\", and \"ORDER BY\" are only "
Expand Down
31 changes: 28 additions & 3 deletions src/duckdb/src/planner/binder/statement/bind_drop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,34 @@ BoundStatement Binder::Bind(DropStatement &stmt) {
// mark catalog as accessed
properties.RegisterDBRead(*catalog, context);
}
EntryLookupInfo entry_lookup(stmt.info->type, stmt.info->name);
auto entry =
Catalog::GetEntry(context, stmt.info->catalog, stmt.info->schema, entry_lookup, stmt.info->if_not_found);
optional_ptr<CatalogEntry> entry;
if (stmt.info->type == CatalogType::MACRO_ENTRY) {
// We also support "DROP MACRO" (instead of "DROP MACRO TABLE") for table macros
// First try to drop a scalar macro
EntryLookupInfo macro_entry_lookup(stmt.info->type, stmt.info->name);
entry = Catalog::GetEntry(context, stmt.info->catalog, stmt.info->schema, macro_entry_lookup,
OnEntryNotFound::RETURN_NULL);
if (!entry) {
// Unable to find a scalar macro, try to drop a table macro
EntryLookupInfo table_macro_entry_lookup(CatalogType::TABLE_MACRO_ENTRY, stmt.info->name);
entry = Catalog::GetEntry(context, stmt.info->catalog, stmt.info->schema, table_macro_entry_lookup,
OnEntryNotFound::RETURN_NULL);
if (entry) {
// Change type to table macro so future lookups get the correct one
stmt.info->type = CatalogType::TABLE_MACRO_ENTRY;
}
}

if (!entry) {
// Unable to find table macro, try again with original OnEntryNotFound to ensure we throw if necessary
entry = Catalog::GetEntry(context, stmt.info->catalog, stmt.info->schema, macro_entry_lookup,
stmt.info->if_not_found);
}
} else {
EntryLookupInfo entry_lookup(stmt.info->type, stmt.info->name);
entry = Catalog::GetEntry(context, stmt.info->catalog, stmt.info->schema, entry_lookup,
stmt.info->if_not_found);
}
if (!entry) {
break;
}
Expand Down
10 changes: 8 additions & 2 deletions src/duckdb/src/storage/table/row_group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -881,15 +881,21 @@ void RowGroup::Update(TransactionData transaction, DataChunk &update_chunk, row_
}
}

void RowGroup::UpdateColumn(TransactionData transaction, DataChunk &updates, Vector &row_ids,
void RowGroup::UpdateColumn(TransactionData transaction, DataChunk &updates, Vector &row_ids, idx_t offset, idx_t count,
const vector<column_t> &column_path) {
D_ASSERT(updates.ColumnCount() == 1);
auto ids = FlatVector::GetData<row_t>(row_ids);

auto primary_column_idx = column_path[0];
D_ASSERT(primary_column_idx < columns.size());
auto &col_data = GetColumn(primary_column_idx);
col_data.UpdateColumn(transaction, column_path, updates.data[0], ids, updates.size(), 1);
if (offset > 0) {
Vector sliced_vector(updates.data[0], offset, offset + count);
sliced_vector.Flatten(count);
col_data.UpdateColumn(transaction, column_path, sliced_vector, ids + offset, count, 1);
} else {
col_data.UpdateColumn(transaction, column_path, updates.data[0], ids, count, 1);
}
MergeStatistics(primary_column_idx, *col_data.GetUpdateStatistics());
}

Expand Down
63 changes: 35 additions & 28 deletions src/duckdb/src/storage/table/row_group_collection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,30 +622,36 @@ idx_t RowGroupCollection::Delete(TransactionData transaction, DataTable &table,
//===--------------------------------------------------------------------===//
// Update
//===--------------------------------------------------------------------===//
optional_ptr<RowGroup> RowGroupCollection::NextUpdateRowGroup(row_t *ids, idx_t &pos, idx_t count) const {
auto row_group = row_groups->GetSegment(UnsafeNumericCast<idx_t>(ids[pos]));

row_t base_id =
UnsafeNumericCast<row_t>(row_group->start + ((UnsafeNumericCast<idx_t>(ids[pos]) - row_group->start) /
STANDARD_VECTOR_SIZE * STANDARD_VECTOR_SIZE));
auto max_id =
MinValue<row_t>(base_id + STANDARD_VECTOR_SIZE, UnsafeNumericCast<row_t>(row_group->start + row_group->count));
for (pos++; pos < count; pos++) {
D_ASSERT(ids[pos] >= 0);
// check if this id still belongs to this vector in this row group
if (ids[pos] < base_id) {
// id is before vector start -> it does not
break;
}
if (ids[pos] >= max_id) {
// id is after the maximum id in this vector -> it does not
break;
}
}
return row_group;
}

void RowGroupCollection::Update(TransactionData transaction, row_t *ids, const vector<PhysicalIndex> &column_ids,
DataChunk &updates) {
D_ASSERT(updates.size() >= 1);
idx_t pos = 0;
do {
idx_t start = pos;
auto row_group = row_groups->GetSegment(UnsafeNumericCast<idx_t>(ids[pos]));
row_t base_id =
UnsafeNumericCast<row_t>(row_group->start + ((UnsafeNumericCast<idx_t>(ids[pos]) - row_group->start) /
STANDARD_VECTOR_SIZE * STANDARD_VECTOR_SIZE));
auto max_id = MinValue<row_t>(base_id + STANDARD_VECTOR_SIZE,
UnsafeNumericCast<row_t>(row_group->start + row_group->count));
for (pos++; pos < updates.size(); pos++) {
D_ASSERT(ids[pos] >= 0);
// check if this id still belongs to this vector in this row group
if (ids[pos] < base_id) {
// id is before vector start -> it does not
break;
}
if (ids[pos] >= max_id) {
// id is after the maximum id in this vector -> it does not
break;
}
}
auto row_group = NextUpdateRowGroup(ids, pos, updates.size());
row_group->Update(transaction, updates, ids, start, pos - start, column_ids);

auto l = stats.GetLock();
Expand Down Expand Up @@ -760,17 +766,18 @@ void RowGroupCollection::RemoveFromIndexes(TableIndexList &indexes, Vector &row_

void RowGroupCollection::UpdateColumn(TransactionData transaction, Vector &row_ids, const vector<column_t> &column_path,
DataChunk &updates) {
auto first_id = FlatVector::GetValue<row_t>(row_ids, 0);
if (first_id >= MAX_ROW_ID) {
throw NotImplementedException("Cannot update a column-path on transaction local data");
}
// find the row_group this id belongs to
auto primary_column_idx = column_path[0];
auto row_group = row_groups->GetSegment(UnsafeNumericCast<idx_t>(first_id));
row_group->UpdateColumn(transaction, updates, row_ids, column_path);
D_ASSERT(updates.size() >= 1);
auto ids = FlatVector::GetData<row_t>(row_ids);
idx_t pos = 0;
do {
idx_t start = pos;
auto row_group = NextUpdateRowGroup(ids, pos, updates.size());
row_group->UpdateColumn(transaction, updates, row_ids, start, pos - start, column_path);

auto lock = stats.GetLock();
row_group->MergeIntoStatistics(primary_column_idx, stats.GetStats(*lock, primary_column_idx).Statistics());
auto lock = stats.GetLock();
auto primary_column_idx = column_path[0];
row_group->MergeIntoStatistics(primary_column_idx, stats.GetStats(*lock, primary_column_idx).Statistics());
} while (pos < updates.size());
}

//===--------------------------------------------------------------------===//
Expand Down
Loading