Skip to content

Commit bff41d9

Browse files
committed
fix: extra try-catch during plugin init.
1 parent 4af16b4 commit bff41d9

5 files changed

Lines changed: 107 additions & 39 deletions

File tree

storage/duckdb/ha_duckdb.cc

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,14 +187,20 @@ static int duckdb_close_connection(handlerton *hton, THD *thd)
187187

188188
static int duckdb_register_trx(THD *thd)
189189
{
190+
auto *ctx= get_duckdb_context(thd);
191+
std::string error_msg;
192+
if (ctx->duckdb_trans_begin(error_msg))
193+
{
194+
my_error(ER_GET_ERRMSG, MYF(0), HA_ERR_GENERIC, error_msg.c_str(),
195+
"DuckDB");
196+
return HA_ERR_GENERIC;
197+
}
198+
190199
trans_register_ha(thd, false, duckdb_hton, 0);
191200

192201
if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
193202
trans_register_ha(thd, true, duckdb_hton, 0);
194203

195-
auto *ctx= get_duckdb_context(thd);
196-
if (!ctx->has_transaction())
197-
ctx->duckdb_trans_begin();
198204
return 0;
199205
}
200206

@@ -209,7 +215,8 @@ static void duckdb_drop_database(handlerton *hton, char *path)
209215
query.append(db.name);
210216
query.append("\"");
211217

212-
duckdb_register_trx(thd);
218+
if (duckdb_register_trx(thd))
219+
DBUG_VOID_RETURN;
213220
auto *ctx= get_duckdb_context(thd);
214221
auto query_result= myduck::duckdb_query(ctx->get_connection(), query);
215222
DBUG_VOID_RETURN;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
connection con1;
2+
BEGIN;
3+
INSERT INTO batch_disconnect VALUES (1);
4+
disconnect con1;
5+
connection default;
6+
INSERT INTO batch_disconnect VALUES (2);
7+
SELECT * FROM batch_disconnect ORDER BY id;
8+
id
9+
2
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
BEGIN;
2+
INSERT INTO batch_rollback VALUES (1);
3+
ROLLBACK;
4+
BEGIN;
5+
INSERT INTO batch_rollback VALUES (2);
6+
COMMIT;
7+
SELECT * FROM batch_rollback ORDER BY id;
8+
id
9+
2

storage/duckdb/runtime/duckdb_context.h

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,29 @@ class DuckdbThdContext
5050

5151
~DuckdbThdContext()
5252
{
53-
if (has_transaction())
54-
{
55-
std::string error_msg;
56-
duckdb_trans_rollback(error_msg);
57-
}
53+
std::string error_msg;
54+
duckdb_trans_rollback(error_msg);
5855
}
5956

6057
bool has_transaction() { return m_con && m_con->HasActiveTransaction(); }
6158

62-
bool duckdb_trans_begin()
59+
bool duckdb_trans_begin(std::string &error_msg)
6360
{
64-
if (!m_con || m_con->HasActiveTransaction())
61+
if (!m_con)
62+
{
63+
error_msg= "DuckDB connection is not available";
6564
return true;
65+
}
66+
if (m_con->HasActiveTransaction())
67+
return false;
68+
6669
auto result= duckdb_query(*m_con, "BEGIN");
67-
return result->HasError();
70+
if (result->HasError())
71+
{
72+
error_msg= result->GetError();
73+
return true;
74+
}
75+
return false;
6876
}
6977

7078
bool duckdb_trans_commit(std::string &error_msg)
@@ -87,6 +95,12 @@ class DuckdbThdContext
8795

8896
bool duckdb_trans_rollback(std::string &error_msg)
8997
{
98+
if (m_appenders)
99+
{
100+
m_appenders->discard_all();
101+
m_appenders.reset();
102+
}
103+
90104
if (!m_con)
91105
return true;
92106

storage/duckdb/runtime/duckdb_manager.cc

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -185,74 +185,103 @@ bool DuckdbManager::Initialize()
185185
return true;
186186
}
187187

188-
/* Enable autoloading of statically-linked extensions (core_functions etc.) */
188+
try
189189
{
190+
/* Enable autoloading of statically-linked extensions (core_functions etc.) */
190191
auto con= std::make_shared<duckdb::Connection>(*m_database);
191-
con->Query("SET autoload_known_extensions=true");
192-
con->Query("SET autoinstall_known_extensions=true");
192+
auto init_query= [&con](const std::string &sql) {
193+
auto result= con->Query(sql);
194+
if (!result)
195+
throw duckdb::InternalException(
196+
"DuckDB initialization query returned no result");
197+
if (result->HasError())
198+
throw duckdb::InvalidInputException(
199+
"DuckDB initialization query failed: %s", result->GetError());
200+
};
201+
init_query("SET autoload_known_extensions=true");
202+
init_query("SET autoinstall_known_extensions=true");
193203

194204
/*
195205
Register MariaDB-compatible SQL macros for functions that DuckDB
196206
lacks but MariaDB pushes down via the original query text.
197207
*/
198-
con->Query("CREATE OR REPLACE MACRO adddate(d, i) AS d + i");
208+
init_query("CREATE OR REPLACE MACRO adddate(d, i) AS d + i");
199209
/* addtime/subtime registered as C++ UDFs */
200210
/* curdate/curtime — MariaDB aliases */
201211
/* datediff(d1, d2) — MariaDB returns days, DuckDB needs 3-arg form */
202-
con->Query("CREATE OR REPLACE MACRO datediff(d1, d2) AS "
212+
init_query("CREATE OR REPLACE MACRO datediff(d1, d2) AS "
203213
"(d1::DATE - d2::DATE)");
204-
con->Query("CREATE OR REPLACE MACRO curdate() AS current_date");
205-
con->Query("CREATE OR REPLACE MACRO curtime(fsp := 0) AS current_time");
214+
init_query("CREATE OR REPLACE MACRO curdate() AS current_date");
215+
init_query("CREATE OR REPLACE MACRO curtime(fsp := 0) AS current_time");
206216
/* utc_time/utc_timestamp/utc_date — UTC wall-clock; fsp ignored */
207-
con->Query("CREATE OR REPLACE MACRO utc_timestamp(fsp := 0) AS "
217+
init_query("CREATE OR REPLACE MACRO utc_timestamp(fsp := 0) AS "
208218
"timezone('UTC', now())::TIMESTAMP");
209-
con->Query("CREATE OR REPLACE MACRO utc_time(fsp := 0) AS "
219+
init_query("CREATE OR REPLACE MACRO utc_time(fsp := 0) AS "
210220
"timezone('UTC', now())::TIME");
211-
con->Query("CREATE OR REPLACE MACRO utc_date() AS "
221+
init_query("CREATE OR REPLACE MACRO utc_date() AS "
212222
"timezone('UTC', now())::DATE");
213223
/* unix_timestamp([ts]) — epoch seconds; no arg = now() */
214-
con->Query("CREATE OR REPLACE MACRO unix_timestamp(ts := now()) AS "
224+
init_query("CREATE OR REPLACE MACRO unix_timestamp(ts := now()) AS "
215225
"epoch(ts)::BIGINT");
216226
/* time_to_sec(t) — seconds since midnight */
217-
con->Query("CREATE OR REPLACE MACRO time_to_sec(t) AS "
227+
init_query("CREATE OR REPLACE MACRO time_to_sec(t) AS "
218228
"(date_part('hour', t)*3600 + date_part('minute', t)*60 "
219229
"+ date_part('second', t))::BIGINT");
220230
/* convert_tz(ts, from_tz, to_tz) */
221-
con->Query("CREATE OR REPLACE MACRO convert_tz(ts, from_tz, to_tz) AS "
231+
init_query("CREATE OR REPLACE MACRO convert_tz(ts, from_tz, to_tz) AS "
222232
"timezone(to_tz, timezone(from_tz, ts))");
223-
con->Query("CREATE OR REPLACE MACRO subdate(d, i) AS d - i");
224-
con->Query("CREATE OR REPLACE MACRO insert(str, pos, len, newstr) AS "
233+
init_query("CREATE OR REPLACE MACRO subdate(d, i) AS d - i");
234+
init_query("CREATE OR REPLACE MACRO insert(str, pos, len, newstr) AS "
225235
"CASE WHEN pos < 1 OR pos > length(str) THEN str "
226236
"ELSE substr(str, 1, pos - 1) || newstr || "
227237
"substr(str, pos + len) END");
228238
/* to_base64 / from_base64 — DuckDB uses base64()/from_base64() */
229-
con->Query("CREATE OR REPLACE MACRO to_base64(x) AS "
239+
init_query("CREATE OR REPLACE MACRO to_base64(x) AS "
230240
"base64(encode(x))");
231241
/* substring_index(str, delim, count) */
232-
con->Query("CREATE OR REPLACE MACRO substring_index(s, d, c) AS "
242+
init_query("CREATE OR REPLACE MACRO substring_index(s, d, c) AS "
233243
"CASE WHEN c > 0 THEN "
234244
"array_to_string(list_slice(string_split(s, d), 1, c), d) "
235245
"WHEN c < 0 THEN "
236246
"array_to_string(list_slice(string_split(s, d), c, NULL), d) "
237247
"ELSE '' END");
238248
/* strcmp(s1, s2) — returns 0, -1 or 1 */
239-
con->Query("CREATE OR REPLACE MACRO strcmp(a, b) AS "
249+
init_query("CREATE OR REPLACE MACRO strcmp(a, b) AS "
240250
"CASE WHEN a = b THEN 0 WHEN a < b THEN -1 ELSE 1 END");
241251
/* MID() registered as C++ UDF in register_mysql_compat_functions() */
242252
/* oct, bin, hex, locate are now registered as native C++ scalar functions
243253
in register_mysql_compat_functions() -- no SQL macros needed. */
244-
}
245-
246-
/* Register MySQL-compatible function overloads */
247-
register_mysql_compat_functions(*m_database->instance);
254+
/* Register MySQL-compatible function overloads */
255+
register_mysql_compat_functions(*m_database->instance);
248256

249-
/* Register cross-engine scan support (_mdb_scan + replacement scan) */
250-
register_cross_engine_scan(*m_database->instance);
257+
/* Register cross-engine scan support (_mdb_scan + replacement scan) */
258+
register_cross_engine_scan(*m_database->instance);
251259

252-
sql_print_information("DuckDB: DuckdbManager::Initialize succeed, path=%s",
253-
path);
260+
sql_print_information("DuckDB: DuckdbManager::Initialize succeed, path=%s",
261+
path);
262+
return false;
263+
}
264+
catch (const std::exception &e)
265+
{
266+
sql_print_error("DuckDB: initialization failed at '%s': %s", path,
267+
e.what());
268+
}
269+
catch (...)
270+
{
271+
sql_print_error("DuckDB: initialization failed at '%s': unknown exception",
272+
path);
273+
}
254274

255-
return false;
275+
try
276+
{
277+
delete m_database;
278+
}
279+
catch (...)
280+
{
281+
sql_print_error("DuckDB: exception during failed initialization cleanup");
282+
}
283+
m_database= nullptr;
284+
return true;
256285
}
257286

258287
bool DuckdbManager::CreateInstance()

0 commit comments

Comments
 (0)