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
29 changes: 26 additions & 3 deletions src/duckdb/extension/core_functions/scalar/date/date_part.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,32 @@ struct DatePart {
return YearWeekFromParts(yyyy, ww);
}

// ISO years >= 1 use yyyy * 100 + week. Year 0 and negative years subtract the week,
// so the function decreases as the week number increases.
static int32_t MinISOYear(date_t input) {
return Date::ExtractISOYearNumber(input);
}
static int32_t MinISOYear(timestamp_t input) {
return Date::ExtractISOYearNumber(Timestamp::GetDate(input));
}
template <class U>
static int32_t MinISOYear(U) {
return 0;
}

template <class T>
static unique_ptr<BaseStatistics> PropagateStatistics(ClientContext &context, FunctionStatisticsInput &input) {
// Endpoint bounds do not contain the values in between once the range reaches the
// subtracted-week encoding. Positive ISO years are non-decreasing in the date.
auto &nstats = input.child_stats[0];
if (!NumericStats::HasMinMax(nstats)) {
return nullptr;
}
auto min = NumericStats::GetMin<T>(nstats);
auto max = NumericStats::GetMax<T>(nstats);
if (min > max || !min.IsFinite() || !max.IsFinite() || MinISOYear(min) < 1) {
return nullptr;
}
return PropagateDatePartStatistics<T, YearWeekOperator>(input.child_stats);
}
};
Expand Down Expand Up @@ -2646,9 +2670,8 @@ ScalarFunctionSet HoursFun::GetFunctions() {
}

ScalarFunctionSet YearWeekFun::GetFunctions() {
auto set = GetDatePartFunction<DatePart::YearWeekOperator>();
set.SetUnaryArgProperties(ArgProperties().NonDecreasing());
return set;
// Not monotone on the full date domain: see YearWeekOperator::YearWeekFromParts.
return GetDatePartFunction<DatePart::YearWeekOperator>();
}

ScalarFunctionSet DayOfMonthFun::GetFunctions() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ bool ExecuteReduce(const idx_t loops, ReduceExecuteInfo &execute_info, LambdaFun
vector<Vector> slices;
const idx_t initial_offset = info.has_initial ? 1 : 0;
for (idx_t i = 0; i < info.column_infos.size() - initial_offset; i++) {
if (info.column_infos[i].vector.get().GetVectorType() == VectorType::CONSTANT_VECTOR) {
if (info.column_infos[initial_offset + i].vector.get().GetVectorType() == VectorType::CONSTANT_VECTOR) {
// only reference constant vectors
input_chunk.data[accumulator_offset + 1 + i].Reference(info.column_infos[initial_offset + i].vector);
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/duckdb/extension/icu/icu-datepart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,8 +702,8 @@ void RegisterICUDatePartFunctions(ExtensionLoader &loader) {
ICUDatePart::AddUnaryPartCodeFunctions<double>("julian", loader, LogicalType::DOUBLE);

// register combinations
ICUDatePart::AddUnaryPartCodeFunctions("yearweek", loader, LogicalType::BIGINT,
ArgProperties().NonDecreasing()); // ISO year and week
// yearweek subtracts the week for ISO year <= 0, so it is not monotone across that range
ICUDatePart::AddUnaryPartCodeFunctions("yearweek", loader, LogicalType::BIGINT);

// register various aliases
ICUDatePart::AddUnaryPartCodeFunctions("dayofmonth", loader);
Expand Down
7 changes: 6 additions & 1 deletion src/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,13 @@ void DuckSchemaEntry::Scan(ClientContext &context, CatalogType type,
}

void DuckSchemaEntry::Scan(CatalogType type, const std::function<void(CatalogEntry &)> &callback) {
Scan(type, VisibilityBound::AllCommitted(), callback);
}

void DuckSchemaEntry::Scan(CatalogType type, VisibilityBound bound,
const std::function<void(CatalogEntry &)> &callback) {
auto &set = GetCatalogSet(type);
set.Scan(callback);
set.Scan(bound, callback);
}

void DuckSchemaEntry::DropEntry(ClientContext &context, DropInfo &info) {
Expand Down
15 changes: 9 additions & 6 deletions src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ DuckTableEntry::DuckTableEntry(Catalog &catalog, SchemaCatalogEntry &schema, Bou
auto column_indexes = unique.GetLogicalIndexes(columns);
if (info.indexes.empty()) {
auto index_info = GetIndexInfo(constraint_type, false, info.base, i);
storage->AddIndex(columns, column_indexes, constraint_type, std::move(index_info));
storage->AddIndex(columns, column_indexes, constraint_type, std::move(index_info), unique.check_mode);
continue;
}

Expand All @@ -197,7 +197,8 @@ DuckTableEntry::DuckTableEntry(Catalog &catalog, SchemaCatalogEntry &schema, Bou
index_storage_info.name = name_info.name;
}

storage->AddIndex(columns, column_indexes, constraint_type, std::move(index_storage_info));
storage->AddIndex(columns, column_indexes, constraint_type, std::move(index_storage_info),
unique.check_mode);
continue;
}

Expand All @@ -215,7 +216,8 @@ DuckTableEntry::DuckTableEntry(Catalog &catalog, SchemaCatalogEntry &schema, Bou
if (info.indexes.empty()) {
auto constraint_type = IndexConstraintType::FOREIGN;
auto index_info = GetIndexInfo(constraint_type, false, info.base, i);
storage->AddIndex(columns, column_indexes, constraint_type, std::move(index_info));
storage->AddIndex(columns, column_indexes, constraint_type, std::move(index_info),
ConstraintCheckMode::DEFAULT);
continue;
}

Expand All @@ -226,7 +228,8 @@ DuckTableEntry::DuckTableEntry(Catalog &catalog, SchemaCatalogEntry &schema, Bou
index_storage_info.name = name_info.name;
}

storage->AddIndex(columns, column_indexes, IndexConstraintType::FOREIGN, std::move(index_storage_info));
storage->AddIndex(columns, column_indexes, IndexConstraintType::FOREIGN, std::move(index_storage_info),
ConstraintCheckMode::DEFAULT);
}
}
}
Expand Down Expand Up @@ -1560,8 +1563,8 @@ optional_ptr<CatalogEntry> DuckTableEntry::GetTrigger(CatalogTransaction transac
return triggers->GetEntry(transaction, name);
}

void DuckTableEntry::ScanTriggersNonTransactional(const std::function<void(CatalogEntry &)> &callback) {
triggers->Scan(callback);
void DuckTableEntry::ScanTriggers(VisibilityBound bound, const std::function<void(CatalogEntry &)> &callback) {
triggers->Scan(bound, callback);
}

bool DuckTableEntry::DropTrigger(CatalogTransaction transaction, const Identifier &name, bool cascade) {
Expand Down
20 changes: 10 additions & 10 deletions src/duckdb/src/catalog/catalog_entry/table_catalog_entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ string TableCatalogEntry::ColumnsToSQL(const ColumnList &columns, const vector<u

// find all columns that have NOT NULL specified, but are NOT primary key columns
logical_index_set_t not_null_columns;
logical_index_map_t<vector<ConstraintTiming>> unique_columns;
logical_index_map_t<vector<ConstraintTiming>> pk_columns;
logical_index_map_t<vector<ConstraintCheckMode>> unique_columns;
logical_index_map_t<vector<ConstraintCheckMode>> pk_columns;
identifier_set_t multi_key_pks;
vector<string> extra_constraints;
for (auto &constraint : constraints) {
Expand All @@ -132,9 +132,9 @@ string TableCatalogEntry::ColumnsToSQL(const ColumnList &columns, const vector<u
if (pk.HasIndex()) {
// no columns specified: single column constraint
if (pk.IsPrimaryKey()) {
pk_columns[pk.GetIndex()].push_back(pk.timing);
pk_columns[pk.GetIndex()].push_back(pk.check_mode);
} else {
unique_columns[pk.GetIndex()].push_back(pk.timing);
unique_columns[pk.GetIndex()].push_back(pk.check_mode);
}
} else {
// multi-column constraint, this constraint needs to go at the end after all columns
Expand Down Expand Up @@ -172,19 +172,19 @@ string TableCatalogEntry::ColumnsToSQL(const ColumnList &columns, const vector<u
}
if (is_single_key_pk) {
// single column pk: insert constraint here
for (auto timing : pk_columns.at(column.Logical())) {
for (auto check_mode : pk_columns.at(column.Logical())) {
ss << " PRIMARY KEY";
if (timing != ConstraintTiming::DEFAULT) {
ss << " " << EnumUtil::ToString(timing);
if (check_mode != ConstraintCheckMode::DEFAULT) {
ss << " " << EnumUtil::ToString(check_mode);
}
}
}
if (is_unique) {
// single column unique: insert constraint here
for (auto timing : unique_columns.at(column.Logical())) {
for (auto check_mode : unique_columns.at(column.Logical())) {
ss << " UNIQUE";
if (timing != ConstraintTiming::DEFAULT) {
ss << " " << EnumUtil::ToString(timing);
if (check_mode != ConstraintCheckMode::DEFAULT) {
ss << " " << EnumUtil::ToString(check_mode);
}
}
}
Expand Down
24 changes: 6 additions & 18 deletions src/duckdb/src/catalog/catalog_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,18 +553,6 @@ CatalogEntry &CatalogSet::GetEntryForTransaction(CatalogTransaction transaction,
return entry.get();
}

CatalogEntry &CatalogSet::GetCommittedEntry(CatalogEntry &current) {
reference<CatalogEntry> entry(current);
while (entry.get().HasChild()) {
if (IsCommitted(entry.get().timestamp.load())) {
// this entry is committed: use it
break;
}
entry = entry.get().Child();
}
return entry.get();
}

SimilarCatalogEntry CatalogSet::SimilarEntry(CatalogTransaction transaction, const Identifier &name) {
unique_lock<mutex> lock(catalog_lock);
CreateDefaultEntries(transaction, lock);
Expand Down Expand Up @@ -787,14 +775,14 @@ void CatalogSet::ScanWithPrefix(CatalogTransaction transaction, const std::funct
}
}

void CatalogSet::Scan(const std::function<void(CatalogEntry &)> &callback) {
void CatalogSet::Scan(VisibilityBound bound, const std::function<void(CatalogEntry &)> &callback) {
// lock the catalog set
lock_guard<mutex> lock(catalog_lock);
CatalogTransaction transaction(catalog.GetDatabase(), MAX_TRANSACTION_ID, bound);
for (auto &kv : map.Entries()) {
auto &entry = *kv.second;
auto &committed_entry = GetCommittedEntry(entry);
if (!committed_entry.deleted) {
callback(committed_entry);
auto &entry = GetEntryForTransaction(transaction, *kv.second);
if (!entry.deleted) {
callback(entry);
}
}
}
Expand All @@ -807,7 +795,7 @@ void CatalogSet::SetDefaultGenerator(unique_ptr<DefaultGenerator> defaults_p) {
void CatalogSet::Verify(Catalog &catalog_p) {
D_ASSERT(&catalog_p == &catalog);
vector<reference<CatalogEntry>> entries;
Scan([&](CatalogEntry &entry) { entries.push_back(entry); });
Scan(VisibilityBound::AllCommitted(), [&](CatalogEntry &entry) { entries.push_back(entry); });
for (auto &entry : entries) {
entry.get().Verify(catalog_p);
}
Expand Down
8 changes: 6 additions & 2 deletions src/duckdb/src/catalog/default/default_views.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ static const DefaultView internal_views[] = {
{"pg_catalog", "pg_constraint",
"SELECT table_oid*1000000+constraint_index oid, constraint_text conname, schema_oid connamespace, CASE "
"constraint_type WHEN 'CHECK' then 'c' WHEN 'UNIQUE' then 'u' WHEN 'PRIMARY KEY' THEN 'p' WHEN 'FOREIGN KEY' THEN "
"'f' ELSE 'x' END contype, false condeferrable, false condeferred, true convalidated, table_oid conrelid, 0 "
"'f' ELSE 'x' END contype, constraint_check_mode = 'DEFERRED' condeferrable, constraint_check_mode = 'DEFERRED' "
"condeferred, true convalidated, table_oid "
"conrelid, 0 "
"contypid, 0 conindid, 0 conparentid, 0 confrelid, NULL confupdtype, NULL confdeltype, NULL confmatchtype, true "
"conislocal, 0 coninhcount, false connoinherit, constraint_column_indexes conkey, NULL confkey, NULL conpfeqop, "
"NULL conppeqop, NULL conffeqop, NULL conexclop, expression conbin FROM duckdb_constraints()"},
Expand Down Expand Up @@ -197,7 +199,9 @@ static const DefaultView internal_views[] = {
{"information_schema", "table_constraints",
"SELECT database_name constraint_catalog, schema_name constraint_schema, constraint_name, database_name "
"table_catalog, schema_name table_schema, table_name, CASE constraint_type WHEN 'NOT NULL' THEN 'CHECK' ELSE "
"constraint_type END constraint_type, 'NO' is_deferrable, 'NO' initially_deferred, 'YES' enforced, 'YES' "
"constraint_type END constraint_type, CASE WHEN constraint_check_mode = 'DEFERRED' THEN 'YES' ELSE 'NO' END "
"is_deferrable, CASE WHEN "
"constraint_check_mode = 'DEFERRED' THEN 'YES' ELSE 'NO' END initially_deferred, 'YES' enforced, 'YES' "
"nulls_distinct FROM duckdb_constraints() WHERE constraint_type = 'PRIMARY KEY' OR constraint_type = 'FOREIGN "
"KEY' OR constraint_type = 'UNIQUE' OR constraint_type = 'CHECK' OR constraint_type = 'NOT NULL';"},
{"information_schema", "constraint_column_usage",
Expand Down
6 changes: 3 additions & 3 deletions src/duckdb/src/catalog/dependency_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,9 +675,9 @@ void DependencyManager::ReorderEntries(catalog_entry_vector_t &entries, ClientCo
ReorderEntries(entries, transaction, false);
}

void DependencyManager::ReorderEntries(catalog_entry_vector_t &entries) {
// Read all committed entries. A checkpoint writes internal entries too
CatalogTransaction transaction(catalog.GetDatabase(), MAX_COMMIT_ID, VisibilityBound::Before(MAX_COMMIT_ID));
void DependencyManager::ReorderEntries(catalog_entry_vector_t &entries, VisibilityBound bound) {
// Read the entries committed below the checkpoint's bound. A checkpoint writes internal entries too
CatalogTransaction transaction(catalog.GetDatabase(), MAX_TRANSACTION_ID, bound);
ReorderEntries(entries, transaction, true);
}

Expand Down
17 changes: 9 additions & 8 deletions src/duckdb/src/catalog/duck_catalog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,12 @@ static void ScanNestedSchemas(CatalogTransaction transaction, SchemaCatalogEntry
});
}

static void ScanNestedSchemas(SchemaCatalogEntry &schema, const std::function<void(SchemaCatalogEntry &)> &callback) {
schema.Scan(CatalogType::SCHEMA_ENTRY, [&](CatalogEntry &entry) {
auto &nested = entry.Cast<SchemaCatalogEntry>();
static void ScanNestedSchemas(VisibilityBound bound, DuckSchemaEntry &schema,
const std::function<void(DuckSchemaEntry &)> &callback) {
schema.Scan(CatalogType::SCHEMA_ENTRY, bound, [&](CatalogEntry &entry) {
auto &nested = entry.Cast<DuckSchemaEntry>();
callback(nested);
ScanNestedSchemas(nested, callback);
ScanNestedSchemas(bound, nested, callback);
});
}

Expand All @@ -188,11 +189,11 @@ void DuckCatalog::ScanSchemas(ClientContext &context, std::function<void(SchemaC
});
}

void DuckCatalog::ScanSchemas(std::function<void(SchemaCatalogEntry &)> callback) {
schemas->Scan([&](CatalogEntry &entry) {
auto &schema = entry.Cast<SchemaCatalogEntry>();
void DuckCatalog::ScanSchemas(VisibilityBound bound, std::function<void(DuckSchemaEntry &)> callback) {
schemas->Scan(bound, [&](CatalogEntry &entry) {
auto &schema = entry.Cast<DuckSchemaEntry>();
callback(schema);
ScanNestedSchemas(schema, callback);
ScanNestedSchemas(bound, schema, callback);
});
}

Expand Down
Loading
Loading