@@ -36,10 +36,48 @@ extern "C" {
36
36
#include " nodes/value.h" // strVal
37
37
#include " utils/fmgrprotos.h" // pg_sequence_last_value
38
38
#include " utils/lsyscache.h" // get_relname_relid
39
+ #include " storage/ipc.h" // on_proc_exit
39
40
}
40
41
41
42
namespace pgduckdb {
42
43
44
+ /*
45
+ * Make sure the hook is registered once for a backend.
46
+ * This flag is also used to get a unique temporary directory name
47
+ * for in-memory duckdb instance, otherwise they clash on the same
48
+ * temporary file names. The fix is on pg_duckdb side until
49
+ * https://github.com/duckdb/duckdb/issues/15173 is resolved.
50
+ */
51
+ static bool set_up_instance_directory_hook = false ;
52
+
53
+ /*
54
+ * The length is 37, because a UUID has 36 characters and we need to add a NULL
55
+ * byte. The approach is the same as for bgw_session_hint.
56
+ */
57
+ static char duckdb_instance_directory[37 ];
58
+ void RemoveTemporaryDirectory (int code = 0 , Datum arg = 0 );
59
+
60
+ std::string
61
+ GetInstanceTempDir () {
62
+ if (!set_up_instance_directory_hook) {
63
+ Datum random_uuid = DirectFunctionCall1 (gen_random_uuid, 0 );
64
+ Datum uuid_datum = DirectFunctionCall1 (uuid_out, random_uuid);
65
+ char *uuid_cstr = DatumGetCString (uuid_datum);
66
+ strcpy (duckdb_instance_directory, uuid_cstr);
67
+
68
+ /* Set up the flag first to avoid re-generating uuid in the hook */
69
+ set_up_instance_directory_hook = true ;
70
+ on_proc_exit (RemoveTemporaryDirectory, 0 );
71
+ }
72
+
73
+ return (std::string)duckdb_temporary_directory + " /" + (std::string)duckdb_instance_directory;
74
+ }
75
+
76
+ void
77
+ RemoveTemporaryDirectory (int /* code*/ , Datum /* arg*/ ) {
78
+ std::filesystem::remove_all (GetInstanceTempDir ());
79
+ }
80
+
43
81
const char *
44
82
GetSessionHint () {
45
83
if (!IsEmptyString (duckdb_motherduck_session_hint)) {
@@ -96,14 +134,19 @@ DuckDBManager::Initialize() {
96
134
std::filesystem::create_directories (duckdb_extension_directory);
97
135
98
136
duckdb::DBConfig config;
137
+
138
+ // Special case for temporary directory, that should be unique for every instance
139
+ std::string instance_temp_directory = GetInstanceTempDir ();
140
+ config.options .temporary_directory = instance_temp_directory;
141
+ std::filesystem::create_directory (instance_temp_directory);
142
+
99
143
config.SetOptionByName (" custom_user_agent" , " pg_duckdb" );
100
144
101
145
SET_DUCKDB_OPTION (allow_unsigned_extensions);
102
146
SET_DUCKDB_OPTION (enable_external_access);
103
147
SET_DUCKDB_OPTION (allow_community_extensions);
104
148
SET_DUCKDB_OPTION (autoinstall_known_extensions);
105
149
SET_DUCKDB_OPTION (autoload_known_extensions);
106
- SET_DUCKDB_OPTION (temporary_directory);
107
150
SET_DUCKDB_OPTION (extension_directory);
108
151
109
152
if (duckdb_maximum_memory > 0 ) {
@@ -215,6 +258,7 @@ DuckDBManager::Reset() {
215
258
delete database;
216
259
database = nullptr ;
217
260
UnclaimBgwSessionHint ();
261
+ RemoveTemporaryDirectory ();
218
262
}
219
263
220
264
int64
0 commit comments