|
12 | 12 | #include "duckdb/main/attached_database.hpp"
|
13 | 13 | #include "storage/postgres_catalog.hpp"
|
14 | 14 | #include "storage/postgres_optimizer.hpp"
|
| 15 | +#include "duckdb/planner/extension_callback.hpp" |
| 16 | +#include "duckdb/main/client_context.hpp" |
| 17 | +#include "duckdb/main/client_context_state.hpp" |
| 18 | +#include "duckdb/main/connection_manager.hpp" |
| 19 | +#include "duckdb/common/error_data.hpp" |
15 | 20 |
|
16 | 21 | using namespace duckdb;
|
17 | 22 |
|
| 23 | +class PostgresExtensionState : public ClientContextState { |
| 24 | +public: |
| 25 | + bool CanRequestRebind() override { |
| 26 | + return true; |
| 27 | + } |
| 28 | + RebindQueryInfo OnPlanningError(ClientContext &context, SQLStatement &statement, ErrorData &error) override { |
| 29 | + if (error.Type() != ExceptionType::BINDER) { |
| 30 | + return RebindQueryInfo::DO_NOT_REBIND; |
| 31 | + } |
| 32 | + auto &extra_info = error.ExtraInfo(); |
| 33 | + auto entry = extra_info.find("error_subtype"); |
| 34 | + if (entry == extra_info.end()) { |
| 35 | + return RebindQueryInfo::DO_NOT_REBIND; |
| 36 | + } |
| 37 | + if (entry->second != "COLUMN_NOT_FOUND") { |
| 38 | + return RebindQueryInfo::DO_NOT_REBIND; |
| 39 | + } |
| 40 | + // clear caches and rebind |
| 41 | + PostgresClearCacheFunction::ClearPostgresCaches(context); |
| 42 | + return RebindQueryInfo::ATTEMPT_TO_REBIND; |
| 43 | + } |
| 44 | +}; |
| 45 | + |
| 46 | +class PostgresExtensionCallback : public ExtensionCallback { |
| 47 | +public: |
| 48 | + void OnConnectionOpened(ClientContext &context) override { |
| 49 | + context.registered_state.insert(make_pair("postgres_extension", make_shared<PostgresExtensionState>())); |
| 50 | + } |
| 51 | +}; |
| 52 | + |
18 | 53 | static void SetPostgresConnectionLimit(ClientContext &context, SetScope scope, Value ¶meter) {
|
19 | 54 | if (scope == SetScope::LOCAL) {
|
20 | 55 | throw InvalidInputException("pg_connection_limit can only be set globally");
|
@@ -78,6 +113,11 @@ static void LoadInternal(DatabaseInstance &db) {
|
78 | 113 | OptimizerExtension postgres_optimizer;
|
79 | 114 | postgres_optimizer.optimize_function = PostgresOptimizer::Optimize;
|
80 | 115 | config.optimizer_extensions.push_back(std::move(postgres_optimizer));
|
| 116 | + |
| 117 | + config.extension_callbacks.push_back(make_uniq<PostgresExtensionCallback>()); |
| 118 | + for(auto &connection : ConnectionManager::Get(db).GetConnectionList()) { |
| 119 | + connection->registered_state.insert(make_pair("postgres_extension", make_shared<PostgresExtensionState>())); |
| 120 | + } |
81 | 121 | }
|
82 | 122 |
|
83 | 123 | void PostgresScannerExtension::Load(DuckDB &db) {
|
|
0 commit comments