Repository: duckdb/duckdb (language: python)

Issue:
Sequences in COPY FROM <database>TO <otherDB> causes Dependency Error
### What happens?

> ./duckdb original.db
v1.1.2 f680b7d08f
Enter ".help" for usage hints.
D create sequence seq start 1;
D create table tbl (id int default nextval('seq'));
D attach 'backup.db';
D copy from database original to backup;
Dependency Error: Error adding dependency for object "tbl" - dependency "seq" is in catalog "original", which does not match the catalog "backup".
Cross catalog dependencies are not supported.

### To Reproduce

```bash
./duckdb original.db
```
```sql
create sequence seq start 1;
create table tbl (id int default nextval('seq'));
attach 'backup.db';
copy from database original to backup;
```
```console
Dependency Error: Error adding dependency for object "tbl" - dependency "seq" is in catalog "original", which does not match the catalog "backup".
Cross catalog dependencies are not supported.
```
### OS:

Windows 10

### DuckDB Version:

1.1.2

### DuckDB Client:

CLI

### Hardware:

_No response_

### Full Name:

johndapps

### Affiliation:

4LP

### What is the latest build you tested with? If possible, we recommend testing with the latest nightly build.

I have tested with a stable release

### Did you include all relevant data sets for reproducing the issue?

Not applicable - the reproduction does not require a data set

### Did you include all code required to reproduce the issue?

- [X] Yes, I have

### Did you include all relevant configuration (e.g., CPU architecture, Python version, Linux distribution) to reproduce the issue?

- [X] Yes, I have


Discussion / hints:
Reproduced, thanks!

Fix patch:
diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp
index cc2a9cd4e17d..aadaf1fcb404 100644
--- a/src/catalog/catalog.cpp
+++ b/src/catalog/catalog.cpp
@@ -396,7 +396,12 @@ vector<CatalogSearchEntry> GetCatalogEntries(CatalogEntryRetriever &retriever, c
 			entries.emplace_back(catalog_name, schema);
 		}
 		if (entries.empty()) {
-			entries.emplace_back(DatabaseManager::GetDefaultDatabase(context), schema);
+			auto &default_entry = search_path.GetDefault();
+			if (!IsInvalidCatalog(default_entry.catalog)) {
+				entries.emplace_back(default_entry.catalog, schema);
+			} else {
+				entries.emplace_back(DatabaseManager::GetDefaultDatabase(context), schema);
+			}
 		}
 	} else if (IsInvalidSchema(schema)) {
 		auto schemas = search_path.GetSchemasForCatalog(catalog);
diff --git a/src/execution/physical_plan_generator.cpp b/src/execution/physical_plan_generator.cpp
index 9dead09094d7..1ac6f61b206b 100644
--- a/src/execution/physical_plan_generator.cpp
+++ b/src/execution/physical_plan_generator.cpp
@@ -13,24 +13,6 @@
 
 namespace duckdb {
 
-class DependencyExtractor : public LogicalOperatorVisitor {
-public:
-	explicit DependencyExtractor(LogicalDependencyList &dependencies) : dependencies(dependencies) {
-	}
-
-protected:
-	unique_ptr<Expression> VisitReplace(BoundFunctionExpression &expr, unique_ptr<Expression> *expr_ptr) override {
-		// extract dependencies from the bound function expression
-		if (expr.function.dependency) {
-			expr.function.dependency(expr, dependencies);
-		}
-		return nullptr;
-	}
-
-private:
-	LogicalDependencyList &dependencies;
-};
-
 PhysicalPlanGenerator::PhysicalPlanGenerator(ClientContext &context) : context(context) {
 }
 
@@ -51,10 +33,6 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(unique_ptr<Logica
 	op->ResolveOperatorTypes();
 	profiler.EndPhase();
 
-	// extract dependencies from the logical plan
-	DependencyExtractor extractor(dependencies);
-	extractor.VisitOperator(*op);
-
 	// then create the main physical plan
 	profiler.StartPhase(MetricsType::PHYSICAL_PLANNER_CREATE_PLAN);
 	auto plan = CreatePlan(*op);
diff --git a/src/function/function_binder.cpp b/src/function/function_binder.cpp
index 9aff648a480e..5a554401f153 100644
--- a/src/function/function_binder.cpp
+++ b/src/function/function_binder.cpp
@@ -16,7 +16,9 @@
 
 namespace duckdb {
 
-FunctionBinder::FunctionBinder(ClientContext &context) : context(context) {
+FunctionBinder::FunctionBinder(ClientContext &context_p) : binder(nullptr), context(context_p) {
+}
+FunctionBinder::FunctionBinder(Binder &binder_p) : binder(&binder_p), context(binder_p.context) {
 }
 
 optional_idx FunctionBinder::BindVarArgsFunctionCost(const SimpleFunction &func, const vector<LogicalType> &arguments) {
@@ -440,7 +442,16 @@ unique_ptr<Expression> FunctionBinder::BindScalarFunction(ScalarFunction bound_f
 
 	if (bound_function.bind) {
 		bind_info = bound_function.bind(context, bound_function, children);
+	} else if (bound_function.bind_extended) {
+		if (!binder) {
+			throw InternalException("Function '%s' has a 'bind_extended' but the FunctionBinder was created without "
+			                        "a reference to a Binder",
+			                        bound_function.name);
+		}
+		ScalarFunctionBindInput bind_input(*binder);
+		bind_info = bound_function.bind_extended(bind_input, bound_function, children);
 	}
+
 	if (bound_function.get_modified_databases && binder) {
 		auto &properties = binder->GetStatementProperties();
 		FunctionModifiedDatabasesInput input(bind_info, properties);
diff --git a/src/function/scalar/sequence/nextval.cpp b/src/function/scalar/sequence/nextval.cpp
index d70168c9a784..b5ae85c86f44 100644
--- a/src/function/scalar/sequence/nextval.cpp
+++ b/src/function/scalar/sequence/nextval.cpp
@@ -29,15 +29,23 @@ struct NextSequenceValueOperator {
 	}
 };
 
-SequenceCatalogEntry &BindSequence(ClientContext &context, string &catalog, string &schema, const string &name) {
+SequenceCatalogEntry &BindSequence(Binder &binder, string &catalog, string &schema, const string &name) {
 	// fetch the sequence from the catalog
+	Binder::BindSchemaOrCatalog(binder.context, catalog, schema);
+	return binder.EntryRetriever()
+	    .GetEntry(CatalogType::SEQUENCE_ENTRY, catalog, schema, name)
+	    ->Cast<SequenceCatalogEntry>();
+}
+
+SequenceCatalogEntry &BindSequenceFromContext(ClientContext &context, string &catalog, string &schema,
+                                              const string &name) {
 	Binder::BindSchemaOrCatalog(context, catalog, schema);
 	return Catalog::GetEntry<SequenceCatalogEntry>(context, catalog, schema, name);
 }
 
-SequenceCatalogEntry &BindSequence(ClientContext &context, const string &name) {
+SequenceCatalogEntry &BindSequence(Binder &binder, const string &name) {
 	auto qname = QualifiedName::Parse(name);
-	return BindSequence(context, qname.catalog, qname.schema, qname.name);
+	return BindSequence(binder, qname.catalog, qname.schema, qname.name);
 }
 
 struct NextValLocalState : public FunctionLocalState {
@@ -81,30 +89,23 @@ static void NextValFunction(DataChunk &args, ExpressionState &state, Vector &res
 	}
 }
 
-static unique_ptr<FunctionData> NextValBind(ClientContext &context, ScalarFunction &,
+static unique_ptr<FunctionData> NextValBind(ScalarFunctionBindInput &bind_input, ScalarFunction &,
                                             vector<unique_ptr<Expression>> &arguments) {
 	if (!arguments[0]->IsFoldable()) {
 		throw NotImplementedException(
 		    "currval/nextval requires a constant sequence - non-constant sequences are no longer supported");
 	}
+	auto &binder = bind_input.binder;
 	// parameter to nextval function is a foldable constant
 	// evaluate the constant and perform the catalog lookup already
-	auto seqname = ExpressionExecutor::EvaluateScalar(context, *arguments[0]);
+	auto seqname = ExpressionExecutor::EvaluateScalar(binder.context, *arguments[0]);
 	if (seqname.IsNull()) {
 		return nullptr;
 	}
-	auto &seq = BindSequence(context, seqname.ToString());
+	auto &seq = BindSequence(binder, seqname.ToString());
 	return make_uniq<NextvalBindData>(seq);
 }
 
-static void NextValDependency(BoundFunctionExpression &expr, LogicalDependencyList &dependencies) {
-	if (!expr.bind_info) {
-		return;
-	}
-	auto &info = expr.bind_info->Cast<NextvalBindData>();
-	dependencies.AddDependency(info.sequence);
-}
-
 void Serialize(Serializer &serializer, const optional_ptr<FunctionData> bind_data, const ScalarFunction &) {
 	auto &next_val_bind_data = bind_data->Cast<NextvalBindData>();
 	serializer.WritePropertyWithDefault(100, "sequence_create_info", next_val_bind_data.create_info);
@@ -118,7 +119,7 @@ unique_ptr<FunctionData> Deserialize(Deserializer &deserializer, ScalarFunction
 	}
 	auto &seq_info = create_info->Cast<CreateSequenceInfo>();
 	auto &context = deserializer.Get<ClientContext &>();
-	auto &sequence = BindSequence(context, seq_info.catalog, seq_info.schema, seq_info.name);
+	auto &sequence = BindSequenceFromContext(context, seq_info.catalog, seq_info.schema, seq_info.name);
 	return make_uniq<NextvalBindData>(sequence);
 }
 
@@ -132,7 +133,8 @@ void NextValModifiedDatabases(ClientContext &context, FunctionModifiedDatabasesI
 
 ScalarFunction NextvalFun::GetFunction() {
 	ScalarFunction next_val("nextval", {LogicalType::VARCHAR}, LogicalType::BIGINT,
-	                        NextValFunction<NextSequenceValueOperator>, NextValBind, NextValDependency);
+	                        NextValFunction<NextSequenceValueOperator>, nullptr, nullptr);
+	next_val.bind_extended = NextValBind;
 	next_val.stability = FunctionStability::VOLATILE;
 	next_val.serialize = Serialize;
 	next_val.deserialize = Deserialize;
@@ -143,7 +145,8 @@ ScalarFunction NextvalFun::GetFunction() {
 
 ScalarFunction CurrvalFun::GetFunction() {
 	ScalarFunction curr_val("currval", {LogicalType::VARCHAR}, LogicalType::BIGINT,
-	                        NextValFunction<CurrentSequenceValueOperator>, NextValBind, NextValDependency);
+	                        NextValFunction<CurrentSequenceValueOperator>, nullptr, nullptr);
+	curr_val.bind_extended = NextValBind;
 	curr_val.stability = FunctionStability::VOLATILE;
 	curr_val.serialize = Serialize;
 	curr_val.deserialize = Deserialize;
diff --git a/src/function/scalar_function.cpp b/src/function/scalar_function.cpp
index 75d74cf50970..a627643fd518 100644
--- a/src/function/scalar_function.cpp
+++ b/src/function/scalar_function.cpp
@@ -10,28 +10,28 @@ ScalarFunctionInfo::~ScalarFunctionInfo() {
 
 ScalarFunction::ScalarFunction(string name, vector<LogicalType> arguments, LogicalType return_type,
                                scalar_function_t function, bind_scalar_function_t bind,
-                               dependency_function_t dependency, function_statistics_t statistics,
+                               bind_scalar_function_extended_t bind_extended, function_statistics_t statistics,
                                init_local_state_t init_local_state, LogicalType varargs, FunctionStability side_effects,
                                FunctionNullHandling null_handling, bind_lambda_function_t bind_lambda)
     : BaseScalarFunction(std::move(name), std::move(arguments), std::move(return_type), side_effects,
                          std::move(varargs), null_handling),
-      function(std::move(function)), bind(bind), init_local_state(init_local_state), dependency(dependency),
+      function(std::move(function)), bind(bind), bind_extended(bind_extended), init_local_state(init_local_state),
       statistics(statistics), bind_lambda(bind_lambda), bind_expression(nullptr), get_modified_databases(nullptr),
       serialize(nullptr), deserialize(nullptr) {
 }
 
 ScalarFunction::ScalarFunction(vector<LogicalType> arguments, LogicalType return_type, scalar_function_t function,
-                               bind_scalar_function_t bind, dependency_function_t dependency,
+                               bind_scalar_function_t bind, bind_scalar_function_extended_t bind_extended,
                                function_statistics_t statistics, init_local_state_t init_local_state,
                                LogicalType varargs, FunctionStability side_effects, FunctionNullHandling null_handling,
                                bind_lambda_function_t bind_lambda)
-    : ScalarFunction(string(), std::move(arguments), std::move(return_type), std::move(function), bind, dependency,
+    : ScalarFunction(string(), std::move(arguments), std::move(return_type), std::move(function), bind, bind_extended,
                      statistics, init_local_state, std::move(varargs), side_effects, null_handling, bind_lambda) {
 }
 
 bool ScalarFunction::operator==(const ScalarFunction &rhs) const {
 	return name == rhs.name && arguments == rhs.arguments && return_type == rhs.return_type && varargs == rhs.varargs &&
-	       bind == rhs.bind && dependency == rhs.dependency && statistics == rhs.statistics &&
+	       bind == rhs.bind && bind_extended == rhs.bind_extended && statistics == rhs.statistics &&
 	       bind_lambda == rhs.bind_lambda;
 }
 
diff --git a/src/include/duckdb/function/function_binder.hpp b/src/include/duckdb/function/function_binder.hpp
index 9f1fb315df3d..53e90b2ef346 100644
--- a/src/include/duckdb/function/function_binder.hpp
+++ b/src/include/duckdb/function/function_binder.hpp
@@ -21,8 +21,10 @@ namespace duckdb {
 //! The FunctionBinder class is responsible for binding functions
 class FunctionBinder {
 public:
+	DUCKDB_API explicit FunctionBinder(Binder &binder);
 	DUCKDB_API explicit FunctionBinder(ClientContext &context);
 
+	optional_ptr<Binder> binder;
 	ClientContext &context;
 
 public:
diff --git a/src/include/duckdb/function/scalar_function.hpp b/src/include/duckdb/function/scalar_function.hpp
index 2a8b15330c00..236356b9af8e 100644
--- a/src/include/duckdb/function/scalar_function.hpp
+++ b/src/include/duckdb/function/scalar_function.hpp
@@ -51,7 +51,6 @@ struct ScalarFunctionInfo {
 
 class Binder;
 class BoundFunctionExpression;
-class LogicalDependencyList;
 class ScalarFunctionCatalogEntry;
 
 struct StatementProperties;
@@ -88,17 +87,25 @@ struct FunctionBindExpressionInput {
 	BoundFunctionExpression &function;
 };
 
+struct ScalarFunctionBindInput {
+	explicit ScalarFunctionBindInput(Binder &binder) : binder(binder) {
+	}
+
+	Binder &binder;
+};
+
 //! The scalar function type
 typedef std::function<void(DataChunk &, ExpressionState &, Vector &)> scalar_function_t;
 //! The type to bind the scalar function and to create the function data
 typedef unique_ptr<FunctionData> (*bind_scalar_function_t)(ClientContext &context, ScalarFunction &bound_function,
                                                            vector<unique_ptr<Expression>> &arguments);
+typedef unique_ptr<FunctionData> (*bind_scalar_function_extended_t)(ScalarFunctionBindInput &bind_input,
+                                                                    ScalarFunction &bound_function,
+                                                                    vector<unique_ptr<Expression>> &arguments);
 //! The type to initialize a thread local state for the scalar function
 typedef unique_ptr<FunctionLocalState> (*init_local_state_t)(ExpressionState &state,
                                                              const BoundFunctionExpression &expr,
                                                              FunctionData *bind_data);
-//! The type to add the dependencies of this BoundFunctionExpression to the set of dependencies
-typedef void (*dependency_function_t)(BoundFunctionExpression &expr, LogicalDependencyList &dependencies);
 //! The type to propagate statistics for this scalar function
 typedef unique_ptr<BaseStatistics> (*function_statistics_t)(ClientContext &context, FunctionStatisticsInput &input);
 //! The type to bind lambda-specific parameter types
@@ -117,15 +124,16 @@ class ScalarFunction : public BaseScalarFunction { // NOLINT: work-around bug in
 public:
 	DUCKDB_API ScalarFunction(string name, vector<LogicalType> arguments, LogicalType return_type,
 	                          scalar_function_t function, bind_scalar_function_t bind = nullptr,
-	                          dependency_function_t dependency = nullptr, function_statistics_t statistics = nullptr,
-	                          init_local_state_t init_local_state = nullptr,
+	                          bind_scalar_function_extended_t bind_extended = nullptr,
+	                          function_statistics_t statistics = nullptr, init_local_state_t init_local_state = nullptr,
 	                          LogicalType varargs = LogicalType(LogicalTypeId::INVALID),
 	                          FunctionStability stability = FunctionStability::CONSISTENT,
 	                          FunctionNullHandling null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING,
 	                          bind_lambda_function_t bind_lambda = nullptr);
 
 	DUCKDB_API ScalarFunction(vector<LogicalType> arguments, LogicalType return_type, scalar_function_t function,
-	                          bind_scalar_function_t bind = nullptr, dependency_function_t dependency = nullptr,
+	                          bind_scalar_function_t bind = nullptr,
+	                          bind_scalar_function_extended_t bind_extended = nullptr,
 	                          function_statistics_t statistics = nullptr, init_local_state_t init_local_state = nullptr,
 	                          LogicalType varargs = LogicalType(LogicalTypeId::INVALID),
 	                          FunctionStability stability = FunctionStability::CONSISTENT,
@@ -136,10 +144,10 @@ class ScalarFunction : public BaseScalarFunction { // NOLINT: work-around bug in
 	scalar_function_t function;
 	//! The bind function (if any)
 	bind_scalar_function_t bind;
+	//! The bind function that receives extra input to perform more complex binding operations (if any)
+	bind_scalar_function_extended_t bind_extended = nullptr;
 	//! Init thread local state for the function (if any)
 	init_local_state_t init_local_state;
-	//! The dependency function (if any)
-	dependency_function_t dependency;
 	//! The statistics propagation function (if any)
 	function_statistics_t statistics;
 	//! The lambda bind function (if any)
diff --git a/src/include/duckdb/planner/binder.hpp b/src/include/duckdb/planner/binder.hpp
index ba6de071e016..7da3b6c5d87f 100644
--- a/src/include/duckdb/planner/binder.hpp
+++ b/src/include/duckdb/planner/binder.hpp
@@ -210,6 +210,9 @@ class Binder : public enable_shared_from_this<Binder> {
 	optional_ptr<SQLStatement> GetRootStatement() {
 		return root_statement;
 	}
+	CatalogEntryRetriever &EntryRetriever() {
+		return entry_retriever;
+	}
 
 	void SetCanContainNulls(bool can_contain_nulls);
 	void SetAlwaysRequireRebind();
@@ -256,7 +259,8 @@ class Binder : public enable_shared_from_this<Binder> {
 	//! Bind the expressions of generated columns to check for errors
 	void BindGeneratedColumns(BoundCreateTableInfo &info);
 	//! Bind the default values of the columns of a table
-	void BindDefaultValues(const ColumnList &columns, vector<unique_ptr<Expression>> &bound_defaults);
+	void BindDefaultValues(const ColumnList &columns, vector<unique_ptr<Expression>> &bound_defaults,
+	                       const string &catalog = "", const string &schema = "");
 	//! Bind a limit value (LIMIT or OFFSET)
 	BoundLimitNode BindLimitValue(OrderBinder &order_binder, unique_ptr<ParsedExpression> limit_val, bool is_percentage,
 	                              bool is_offset);
diff --git a/src/planner/binder/expression/bind_aggregate_expression.cpp b/src/planner/binder/expression/bind_aggregate_expression.cpp
index c58214a002c2..97d690c3dcca 100644
--- a/src/planner/binder/expression/bind_aggregate_expression.cpp
+++ b/src/planner/binder/expression/bind_aggregate_expression.cpp
@@ -240,7 +240,7 @@ BindResult BaseSelectBinder::BindAggregate(FunctionExpression &aggr, AggregateFu
 	}
 
 	// bind the aggregate
-	FunctionBinder function_binder(context);
+	FunctionBinder function_binder(binder);
 	auto best_function = function_binder.BindFunction(func.name, func.functions, types, error);
 	if (!best_function.IsValid()) {
 		error.AddQueryLocation(aggr);
diff --git a/src/planner/binder/expression/bind_function_expression.cpp b/src/planner/binder/expression/bind_function_expression.cpp
index 0477c0481db8..6af70584b717 100644
--- a/src/planner/binder/expression/bind_function_expression.cpp
+++ b/src/planner/binder/expression/bind_function_expression.cpp
@@ -125,7 +125,7 @@ BindResult ExpressionBinder::BindFunction(FunctionExpression &function, ScalarFu
 		children.push_back(std::move(child));
 	}
 
-	FunctionBinder function_binder(context);
+	FunctionBinder function_binder(binder);
 	auto result = function_binder.BindScalarFunction(func, std::move(children), error, function.is_operator, &binder);
 	if (!result) {
 		error.AddQueryLocation(function);
@@ -218,7 +218,7 @@ BindResult ExpressionBinder::BindLambdaFunction(FunctionExpression &function, Sc
 	auto &bound_lambda_expr = children.back()->Cast<BoundLambdaExpression>();
 	CaptureLambdaColumns(bound_lambda_expr, bound_lambda_expr.lambda_expr, &bind_lambda_function, list_child_type);
 
-	FunctionBinder function_binder(context);
+	FunctionBinder function_binder(binder);
 	unique_ptr<Expression> result =
 	    function_binder.BindScalarFunction(func, std::move(children), error, function.is_operator, &binder);
 	if (!result) {
diff --git a/src/planner/binder/query_node/bind_select_node.cpp b/src/planner/binder/query_node/bind_select_node.cpp
index 93e0b60c5a7f..1d61ae056e1a 100644
--- a/src/planner/binder/query_node/bind_select_node.cpp
+++ b/src/planner/binder/query_node/bind_select_node.cpp
@@ -497,7 +497,7 @@ unique_ptr<BoundQueryNode> Binder::BindSelectNode(SelectNode &statement, unique_
 				// FIXME: would be better to just refer to this expression, but for now we copy
 				first_children.push_back(bound_expr_ref.Copy());
 
-				FunctionBinder function_binder(context);
+				FunctionBinder function_binder(*this);
 				auto function = function_binder.BindAggregateFunction(first_fun, std::move(first_children));
 				function->alias = "__collated_group";
 				result->aggregates.push_back(std::move(function));
diff --git a/src/planner/binder/query_node/plan_subquery.cpp b/src/planner/binder/query_node/plan_subquery.cpp
index 807fa6c7b494..4b5857f573e7 100644
--- a/src/planner/binder/query_node/plan_subquery.cpp
+++ b/src/planner/binder/query_node/plan_subquery.cpp
@@ -37,7 +37,7 @@ static unique_ptr<Expression> PlanUncorrelatedSubquery(Binder &binder, BoundSubq
 		// now we push a COUNT(*) aggregate onto the limit, this will be either 0 or 1 (EXISTS or NOT EXISTS)
 		auto count_star_fun = CountStarFun::GetFunction();
 
-		FunctionBinder function_binder(binder.context);
+		FunctionBinder function_binder(binder);
 		auto count_star =
 		    function_binder.BindAggregateFunction(count_star_fun, {}, nullptr, AggregateType::NON_DISTINCT);
 		auto idx_type = count_star->return_type;
@@ -87,7 +87,7 @@ static unique_ptr<Expression> PlanUncorrelatedSubquery(Binder &binder, BoundSubq
 		vector<unique_ptr<Expression>> first_children;
 		first_children.push_back(std::move(bound));
 
-		FunctionBinder function_binder(binder.context);
+		FunctionBinder function_binder(binder);
 		auto first_agg =
 		    function_binder.BindAggregateFunction(FirstFunctionGetter::GetFunction(expr.return_type),
 		                                          std::move(first_children), nullptr, AggregateType::NON_DISTINCT);
diff --git a/src/planner/binder/statement/bind_create_table.cpp b/src/planner/binder/statement/bind_create_table.cpp
index 670bdf58661e..6a6bd564da23 100644
--- a/src/planner/binder/statement/bind_create_table.cpp
+++ b/src/planner/binder/statement/bind_create_table.cpp
@@ -262,7 +262,21 @@ void Binder::BindGeneratedColumns(BoundCreateTableInfo &info) {
 	}
 }
 
-void Binder::BindDefaultValues(const ColumnList &columns, vector<unique_ptr<Expression>> &bound_defaults) {
+void Binder::BindDefaultValues(const ColumnList &columns, vector<unique_ptr<Expression>> &bound_defaults,
+                               const string &catalog_name, const string &schema_p) {
+	string schema_name = schema_p;
+	if (schema_p.empty()) {
+		schema_name = DEFAULT_SCHEMA;
+	}
+
+	// FIXME: We might want to save the existing search path of the binder
+	vector<CatalogSearchEntry> defaults_search_path;
+	defaults_search_path.emplace_back(catalog_name, schema_name);
+	if (schema_name != DEFAULT_SCHEMA) {
+		defaults_search_path.emplace_back(catalog_name, DEFAULT_SCHEMA);
+	}
+	entry_retriever.SetSearchPath(std::move(defaults_search_path));
+
 	for (auto &column : columns.Physical()) {
 		unique_ptr<Expression> bound_default;
 		if (column.HasDefaultValue()) {
@@ -283,32 +297,6 @@ void Binder::BindDefaultValues(const ColumnList &columns, vector<unique_ptr<Expr
 	}
 }
 
-static void ExtractExpressionDependencies(Expression &expr, LogicalDependencyList &dependencies) {
-	if (expr.type == ExpressionType::BOUND_FUNCTION) {
-		auto &function = expr.Cast<BoundFunctionExpression>();
-		if (function.function.dependency) {
-			function.function.dependency(function, dependencies);
-		}
-	}
-	ExpressionIterator::EnumerateChildren(
-	    expr, [&](Expression &child) { ExtractExpressionDependencies(child, dependencies); });
-}
-
-static void ExtractDependencies(BoundCreateTableInfo &info, vector<unique_ptr<Expression>> &defaults,
-                                vector<unique_ptr<BoundConstraint>> &constraints) {
-	for (auto &default_value : defaults) {
-		if (default_value) {
-			ExtractExpressionDependencies(*default_value, info.dependencies);
-		}
-	}
-	for (auto &constraint : constraints) {
-		if (constraint->type == ConstraintType::CHECK) {
-			auto &bound_check = constraint->Cast<BoundCheckConstraint>();
-			ExtractExpressionDependencies(*bound_check.expression, info.dependencies);
-		}
-	}
-}
-
 unique_ptr<BoundCreateTableInfo> Binder::BindCreateTableInfo(unique_ptr<CreateInfo> info, SchemaCatalogEntry &schema) {
 	vector<unique_ptr<Expression>> bound_defaults;
 	return BindCreateTableInfo(std::move(info), schema, bound_defaults);
@@ -376,10 +364,10 @@ unique_ptr<BoundCreateTableInfo> Binder::BindCreateTableInfo(unique_ptr<CreateIn
 		// bind any constraints
 		bound_constraints = BindNewConstraints(base.constraints, base.table, base.columns);
 		// bind the default values
-		BindDefaultValues(base.columns, bound_defaults);
+		auto &catalog_name = schema.ParentCatalog().GetName();
+		auto &schema_name = schema.name;
+		BindDefaultValues(base.columns, bound_defaults, catalog_name, schema_name);
 	}
-	// extract dependencies from any default values or CHECK constraints
-	ExtractDependencies(*result, bound_defaults, bound_constraints);
 
 	if (base.columns.PhysicalColumnCount() == 0) {
 		throw BinderException("Creating a table without physical (non-generated) columns is not supported");
diff --git a/src/planner/binder/statement/bind_insert.cpp b/src/planner/binder/statement/bind_insert.cpp
index f02be80009d1..adc3a1d7c1af 100644
--- a/src/planner/binder/statement/bind_insert.cpp
+++ b/src/planner/binder/statement/bind_insert.cpp
@@ -540,7 +540,9 @@ BoundStatement Binder::Bind(InsertStatement &stmt) {
 	}
 
 	// bind the default values
-	BindDefaultValues(table.GetColumns(), insert->bound_defaults);
+	auto &catalog_name = table.ParentCatalog().GetName();
+	auto &schema_name = table.ParentSchema().name;
+	BindDefaultValues(table.GetColumns(), insert->bound_defaults, catalog_name, schema_name);
 	insert->bound_constraints = BindConstraints(table);
 	if (!stmt.select_statement && !stmt.default_values) {
 		result.plan = std::move(insert);
diff --git a/src/planner/binder/statement/bind_pragma.cpp b/src/planner/binder/statement/bind_pragma.cpp
index 8f89dec5b667..3955cf89753e 100644
--- a/src/planner/binder/statement/bind_pragma.cpp
+++ b/src/planner/binder/statement/bind_pragma.cpp
@@ -29,7 +29,7 @@ unique_ptr<BoundPragmaInfo> Binder::BindPragma(PragmaInfo &info, QueryErrorConte
 
 	// bind the pragma function
 	auto &entry = Catalog::GetEntry<PragmaFunctionCatalogEntry>(context, INVALID_CATALOG, DEFAULT_SCHEMA, info.name);
-	FunctionBinder function_binder(context);
+	FunctionBinder function_binder(*this);
 	ErrorData error;
 	auto bound_idx = function_binder.BindFunction(entry.name, entry.functions, params, error);
 	if (!bound_idx.IsValid()) {
diff --git a/src/planner/binder/statement/bind_update.cpp b/src/planner/binder/statement/bind_update.cpp
index 4e27e161042a..83afa5a8681e 100644
--- a/src/planner/binder/statement/bind_update.cpp
+++ b/src/planner/binder/statement/bind_update.cpp
@@ -106,7 +106,9 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) {
 		update->return_chunk = true;
 	}
 	// bind the default values
-	BindDefaultValues(table.GetColumns(), update->bound_defaults);
+	auto &catalog_name = table.ParentCatalog().GetName();
+	auto &schema_name = table.ParentSchema().name;
+	BindDefaultValues(table.GetColumns(), update->bound_defaults, catalog_name, schema_name);
 	update->bound_constraints = BindConstraints(table);
 
 	// project any additional columns required for the condition/expressions
diff --git a/src/planner/binder/tableref/bind_table_function.cpp b/src/planner/binder/tableref/bind_table_function.cpp
index 79972fefb869..f4efdd7dec2d 100644
--- a/src/planner/binder/tableref/bind_table_function.cpp
+++ b/src/planner/binder/tableref/bind_table_function.cpp
@@ -306,7 +306,7 @@ unique_ptr<BoundTableRef> Binder::Bind(TableFunctionRef &ref) {
 	}
 
 	// select the function based on the input parameters
-	FunctionBinder function_binder(context);
+	FunctionBinder function_binder(*this);
 	auto best_function_idx = function_binder.BindFunction(function.name, function.functions, arguments, error);
 	if (!best_function_idx.IsValid()) {
 		error.AddQueryLocation(ref);


Test patch:
diff --git a/test/fuzzer/pedro/temp_sequence_reconnect.test b/test/fuzzer/pedro/temp_sequence_reconnect.test
index 6b781bf0ef15..7feda944cbf7 100644
--- a/test/fuzzer/pedro/temp_sequence_reconnect.test
+++ b/test/fuzzer/pedro/temp_sequence_reconnect.test
@@ -13,22 +13,20 @@ statement ok
 CREATE SEQUENCE t1;
 
 statement ok
-CREATE TABLE t1 (c1 INT, CHECK(nextval('t1')));
+CREATE TABLE t1 (
+	c1 INT,
+	CHECK(nextval('t1'))
+);
 
 statement ok
 CREATE TEMP SEQUENCE t1;
 
-statement error
+statement ok
 ALTER TABLE t1 ADD c0 INT;
-----
-Cross catalog dependencies are not supported
 
 statement ok
 DROP SEQUENCE temp.t1
 
-statement ok
-ALTER TABLE t1 ADD c0 INT;
-
 reconnect
 
 statement ok
diff --git a/test/sql/attach/attach_sequence.test b/test/sql/attach/attach_sequence.test
index 90e2ef852d73..78d66fc71550 100644
--- a/test/sql/attach/attach_sequence.test
+++ b/test/sql/attach/attach_sequence.test
@@ -13,7 +13,7 @@ CREATE SEQUENCE seq;
 statement error
 CREATE TABLE db1.integers(i INTEGER DEFAULT nextval('seq'))
 ----
-Cross catalog dependencies are not supported
+TransactionContext Error: Attempting to write to database "db1" in a transaction that has already modified database
 
 statement ok
 CREATE SEQUENCE db1.seq
@@ -34,7 +34,7 @@ SELECT nextval('seq')
 statement error
 CREATE TABLE integers(i INTEGER DEFAULT nextval('db1.seq'))
 ----
-Cross catalog dependencies are not supported
+<REGEX>:TransactionContext Error:.*in a transaction that has already modified database "db1".*
 
 statement ok
 detach db1;
diff --git a/test/sql/copy_database/copy_table_with_sequence.test b/test/sql/copy_database/copy_table_with_sequence.test
new file mode 100644
index 000000000000..65b87ed4a677
--- /dev/null
+++ b/test/sql/copy_database/copy_table_with_sequence.test
@@ -0,0 +1,108 @@
+# name: test/sql/copy_database/copy_table_with_sequence.test
+# group: [copy_database]
+
+require noforcestorage
+
+statement ok
+pragma enable_verification;
+
+statement ok
+attach '__TEST_DIR__/backup.db';
+
+## Only specifying a sequence name
+
+statement ok
+create sequence seq start 1;
+
+statement ok
+create table tbl (
+	id int default nextval('seq')
+);
+
+statement ok
+insert into tbl values (DEFAULT);
+insert into tbl values (DEFAULT);
+
+statement ok
+copy from database memory to backup;
+
+statement ok
+drop sequence seq cascade;
+
+query I
+select * from backup.tbl;
+----
+1
+2
+
+query I
+select currval('backup.main.seq');
+----
+3
+
+statement ok
+drop sequence backup.main.seq cascade;
+
+## Explicitly specifying the schema
+
+statement ok
+create schema my_schema;
+
+statement ok
+create sequence my_schema.seq start 1;
+
+statement ok
+create table tbl (
+	id int default nextval('my_schema.seq')
+);
+
+statement ok
+copy from database memory to backup;
+
+statement ok
+drop sequence my_schema.seq cascade;
+
+statement ok
+drop sequence backup.my_schema.seq cascade;
+
+## Explicitly specifying the schema, with the same name as the catalog
+
+statement ok
+create schema backup;
+
+statement ok
+create sequence memory.backup.seq start 1;
+
+statement error
+create table tbl (
+	id int default nextval('backup.seq')
+);
+----
+Ambiguous reference to catalog or schema "backup"
+
+statement ok
+drop schema backup cascade;
+
+## Explicitly specifying the catalog + schema (results in an error)
+
+statement ok
+create schema backup;
+
+statement ok
+create sequence memory.backup.seq start 1;
+
+statement ok
+create table tbl (
+	id int default nextval('memory.backup.seq')
+);
+
+statement error
+copy from database memory to backup;
+----
+<REGEX>:TransactionContext Error: Attempting to write to database .* in a transaction that has already modified database .*
+
+statement ok
+drop sequence memory.backup.seq cascade;
+
+statement ok
+drop sequence backup.backup.seq cascade;