diff --git a/ibis/backends/base/sql/alchemy/__init__.py b/ibis/backends/base/sql/alchemy/__init__.py index 6da065b1ff77..c4a20405a1f2 100644 --- a/ibis/backends/base/sql/alchemy/__init__.py +++ b/ibis/backends/base/sql/alchemy/__init__.py @@ -473,6 +473,12 @@ def insert( 'yet implemented' ) + # If we've been passed a `memtable`, pull out the underlying dataframe + if isinstance(obj, ir.Table) and isinstance( + in_mem_table := obj.op(), ops.InMemoryTable + ): + obj = in_mem_table.data.to_frame() + if isinstance(obj, pd.DataFrame): obj.to_sql( table_name, diff --git a/ibis/backends/tests/test_client.py b/ibis/backends/tests/test_client.py index 16d055ee0198..dbcdc3641cdb 100644 --- a/ibis/backends/tests/test_client.py +++ b/ibis/backends/tests/test_client.py @@ -349,6 +349,21 @@ def _emp(a, b, c, d): assert len(alchemy_con.table(employee_data_1_temp_table).execute()) == 3 +def test_insert_from_memtable(alchemy_con): + df = pd.DataFrame({"x": range(3)}) + table_name = "memtable_test" + alchemy_con.insert(table_name, ibis.memtable(df)) + alchemy_con.insert(table_name, ibis.memtable(df)) + + try: + table = alchemy_con.tables[table_name] + assert len(table.execute()) == 6 + assert alchemy_con.tables[table_name].schema() == ibis.schema({"x": "int64"}) + finally: + alchemy_con.raw_sql(f"DROP TABLE IF EXISTS {table_name}") + assert table_name not in alchemy_con.list_tables() + + def test_list_databases(alchemy_con): # Every backend has its own databases TEST_DATABASES = {