Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions storage/duckdb/mysql-test/duckdb/r/mdev_40868.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
call mtr.add_suppression("FIBER: execution error");
CREATE TABLE t1 (c2 DATETIME);
INSERT INTO t1 VALUES ('0000-00-00');
CREATE TABLE t2 (c1 INT PRIMARY KEY) ENGINE=DuckDB;
SELECT * FROM t2 UNION SELECT * FROM t1;
c1
SELECT 1 AS still_alive;
still_alive
1
DROP TABLE t2;
DROP TABLE t1;
25 changes: 25 additions & 0 deletions storage/duckdb/mysql-test/duckdb/t/mdev_40868.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--source ../include/have_duckdb.inc
--source include/not_msan.inc
--disable_warnings

#
# MDEV-40868 SIGABRT in duckdb::Value::CastAs on UNION of DuckDB
# and InnoDB table. Invalid DATETIME '0000-00-00' used to throw
# out of select_to_duckdb::send_data and abort the server.
# send_data now converts the exception into a THD error and returns
# -1; the fiber scan finishes without crashing.
#

call mtr.add_suppression("FIBER: execution error");

CREATE TABLE t1 (c2 DATETIME);
INSERT INTO t1 VALUES ('0000-00-00');
CREATE TABLE t2 (c1 INT PRIMARY KEY) ENGINE=DuckDB;

SELECT * FROM t2 UNION SELECT * FROM t1;

# Server must still be usable after the conversion error.
SELECT 1 AS still_alive;

DROP TABLE t2;
DROP TABLE t1;
48 changes: 31 additions & 17 deletions storage/duckdb/runtime/fiber_scan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,29 +102,43 @@ select_to_duckdb::select_to_duckdb(THD *thd_arg,

int select_to_duckdb::send_data(List<Item> &items)
{
List_iterator_fast<Item> it(items);
Item *item;
duckdb::idx_t col= 0;

while ((item= it++))
try
{
if (col < types_->size())
List_iterator_fast<Item> it(items);
Item *item;
duckdb::idx_t col= 0;

while ((item= it++))
{
duckdb::Value val= item_to_duckdb_value(item, (*types_)[col]);
buffer_->data[col].SetValue(row_count_, val);
if (col < types_->size())
{
duckdb::Value val= item_to_duckdb_value(item, (*types_)[col]);
buffer_->data[col].SetValue(row_count_, val);
}
col++;
}
row_count_++;

if (row_count_ >= STANDARD_VECTOR_SIZE)
{
buffer_->SetCardinality(row_count_);
row_count_= 0;
fiber_context_yield(ctx_);
}
col++;
}
row_count_++;

if (row_count_ >= STANDARD_VECTOR_SIZE)
return thd->killed ? -1 : 0;
}
catch (const std::exception &ex)
{
buffer_->SetCardinality(row_count_);
row_count_= 0;
fiber_context_yield(ctx_);
my_error(ER_GET_ERRMSG, MYF(0), HA_ERR_GENERIC, ex.what(), "DuckDB");
return -1;
}
catch (...)
{
my_error(ER_GET_ERRMSG, MYF(0), HA_ERR_GENERIC,
"Unknown error converting row to DuckDB", "DuckDB");
return -1;
}

return thd->killed ? -1 : 0;
}

bool select_to_duckdb::send_eof()
Expand Down