6
6
#include " duckdb/parser/parsed_data/drop_info.hpp"
7
7
#include " duckdb/parser/parsed_data/create_schema_info.hpp"
8
8
#include " duckdb/main/attached_database.hpp"
9
+ #include " duckdb/main/secret/secret_manager.hpp"
9
10
10
11
namespace duckdb {
11
12
12
- PostgresCatalog::PostgresCatalog (AttachedDatabase &db_p, const string &path , AccessMode access_mode,
13
+ PostgresCatalog::PostgresCatalog (AttachedDatabase &db_p, string connection_string_p, string attach_path_p , AccessMode access_mode,
13
14
string schema_to_load)
14
- : Catalog(db_p), path(path ), access_mode(access_mode), schemas(*this , schema_to_load), connection_pool(*this ),
15
+ : Catalog(db_p), connection_string(std::move(connection_string_p)), attach_path(std::move(attach_path_p) ), access_mode(access_mode), schemas(*this , schema_to_load), connection_pool(*this ),
15
16
default_schema (schema_to_load) {
16
17
if (default_schema.empty ()) {
17
18
default_schema = " public" ;
@@ -26,6 +27,80 @@ PostgresCatalog::PostgresCatalog(AttachedDatabase &db_p, const string &path, Acc
26
27
this ->version = connection.GetConnection ().GetPostgresVersion ();
27
28
}
28
29
30
+ string EscapeConnectionString (const string &input) {
31
+ string result = " '" ;
32
+ for (auto c : input) {
33
+ if (c == ' \\ ' ) {
34
+ result += " \\\\ " ;
35
+ } else if (c == ' \' ' ) {
36
+ result += " \\ '" ;
37
+ } else {
38
+ result += c;
39
+ }
40
+ }
41
+ result += " '" ;
42
+ return result;
43
+ }
44
+
45
+ string AddConnectionOption (const KeyValueSecret &kv_secret, const string &name) {
46
+ Value input_val = kv_secret.TryGetValue (name);
47
+ if (input_val.IsNull ()) {
48
+ // not provided
49
+ return string ();
50
+ }
51
+ string result;
52
+ result += name;
53
+ result += " =" ;
54
+ result += EscapeConnectionString (input_val.ToString ());
55
+ result += " " ;
56
+ return result;
57
+ }
58
+
59
+ unique_ptr<SecretEntry> GetSecret (ClientContext &context, const string &secret_name) {
60
+ auto &secret_manager = SecretManager::Get (context);
61
+ auto transaction = CatalogTransaction::GetSystemCatalogTransaction (context);
62
+ // FIXME: this should be adjusted once the `GetSecretByName` API supports this use case
63
+ auto secret_entry = secret_manager.GetSecretByName (transaction, secret_name, " memory" );
64
+ if (secret_entry) {
65
+ return secret_entry;
66
+ }
67
+ secret_entry = secret_manager.GetSecretByName (transaction, secret_name, " local_file" );
68
+ if (secret_entry) {
69
+ return secret_entry;
70
+ }
71
+ return nullptr ;
72
+ }
73
+
74
+ string PostgresCatalog::GetConnectionString (ClientContext &context, const string &attach_path, string secret_name) {
75
+ // if no secret is specified we default to the unnamed postgres secret, if it exists
76
+ string connection_string = attach_path;
77
+ bool explicit_secret = !secret_name.empty ();
78
+ if (!explicit_secret) {
79
+ // look up settings from the default unnamed postgres secret if none is provided
80
+ secret_name = " __default_postgres" ;
81
+ }
82
+
83
+ auto secret_entry = GetSecret (context, secret_name);
84
+ if (secret_entry) {
85
+ // secret found - read data
86
+ const auto &kv_secret = dynamic_cast <const KeyValueSecret &>(*secret_entry->secret );
87
+ string new_connection_info;
88
+
89
+ new_connection_info += AddConnectionOption (kv_secret, " user" );
90
+ new_connection_info += AddConnectionOption (kv_secret, " password" );
91
+ new_connection_info += AddConnectionOption (kv_secret, " host" );
92
+ new_connection_info += AddConnectionOption (kv_secret, " port" );
93
+ new_connection_info += AddConnectionOption (kv_secret, " dbname" );
94
+
95
+ connection_string = new_connection_info + connection_string;
96
+ } else if (explicit_secret) {
97
+ // secret not found and one was explicitly provided - throw an error
98
+ throw BinderException (" Secret with name \" %s\" not found" , secret_name);
99
+ }
100
+ return connection_string;
101
+ }
102
+
103
+
29
104
PostgresCatalog::~PostgresCatalog () = default ;
30
105
31
106
void PostgresCatalog::Initialize (bool load_builtin) {
@@ -85,7 +160,7 @@ bool PostgresCatalog::InMemory() {
85
160
}
86
161
87
162
string PostgresCatalog::GetDBPath () {
88
- return path ;
163
+ return attach_path ;
89
164
}
90
165
91
166
DatabaseSize PostgresCatalog::GetDatabaseSize (ClientContext &context) {
0 commit comments