Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions marimo/_runtime/dataflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,11 +331,19 @@ def register_cell(self, cell_id: CellId_t, cell: CellImpl) -> None:
if sql_ref:
sql_matches = self._find_sql_hierarchical_matches(sql_ref)
for matching_cell_ids, _ in sql_matches:
if cell_id in matching_cell_ids:
LOGGER.debug(
"Cell %s is referencing itself", cell_id
)
continue
other_ids_defining_name.update(matching_cell_ids)

# If other_ids_defining_name is empty, the user will get a
# NameError at runtime (unless the symbol is a builtin).
for other_id in other_ids_defining_name:
if other_id == cell_id:
LOGGER.error("Cell %s is referencing itself", cell_id)
continue
if not self._is_valid_cell_reference(
other_id, variable_name
):
Expand Down
98 changes: 98 additions & 0 deletions tests/_runtime/test_dataflow_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,104 @@ def __post_init__(self) -> None:
},
expected_defs={"0": ["my_db"], "1": ["my_table"], "2": [], "3": []},
),
GraphTestCase(
name="create table with the same name from a different schema",
enabled=HAS_DUCKDB,
code={
"0": "_ = mo.sql(f'CREATE TABLE my_table AS SELECT * FROM schema_one.my_table')",
"1": "_ = mo.sql(f'SELECT * FROM my_table')",
},
expected_parents={"0": [], "1": ["0"]},
expected_children={"0": ["1"], "1": []},
expected_refs={
"0": ["mo", "schema_one.my_table"],
"1": ["mo", "my_table"],
},
expected_defs={"0": ["my_table"], "1": []},
),
GraphTestCase(
name="create table with the same name from catalog.schema hierarchy",
enabled=HAS_DUCKDB,
code={
"0": "_ = mo.sql(f'CREATE TABLE my_table AS SELECT * FROM catalog_one.schema_one.my_table')",
"1": "_ = mo.sql(f'SELECT * FROM my_table')",
},
expected_parents={"0": [], "1": ["0"]},
expected_children={"0": ["1"], "1": []},
expected_refs={
"0": ["mo", "catalog_one.schema_one.my_table"],
"1": ["mo", "my_table"],
},
expected_defs={"0": ["my_table"], "1": []},
),
GraphTestCase(
name="create schema with the same name from a different catalog",
enabled=HAS_DUCKDB,
code={
"0": "_ = mo.sql(f'CREATE SCHEMA my_schema')",
"1": "_ = mo.sql(f'CREATE TABLE my_schema.my_table AS SELECT * FROM catalog_one.my_schema.my_table')",
"2": "_ = mo.sql(f'SELECT * FROM my_schema.my_table')",
},
expected_parents={"0": [], "1": ["0"], "2": ["0", "1"]},
expected_children={"0": ["1", "2"], "1": ["2"], "2": []},
expected_refs={
"0": ["mo"],
"1": ["mo", "catalog_one.my_schema.my_table", "my_schema"],
"2": ["mo", "my_schema.my_table"],
},
expected_defs={"0": ["my_schema"], "1": ["my_table"], "2": []},
),
GraphTestCase(
name="create table that references itself in join prevents self-loop",
enabled=HAS_DUCKDB,
code={
"0": "_ = mo.sql(f'CREATE TABLE users AS SELECT 1 as id')",
"1": "_ = mo.sql(f'CREATE TABLE orders AS SELECT u.id FROM schema_one.users u JOIN schema_two.orders o ON u.id = o.user_id')",
"2": "_ = mo.sql(f'SELECT * FROM orders')",
},
expected_parents={"0": [], "1": [], "2": ["1"]},
expected_children={"0": [], "1": ["2"], "2": []},
expected_refs={
"0": ["mo"],
"1": ["mo", "schema_one.users", "schema_two.orders"],
"2": ["mo", "orders"],
},
expected_defs={"0": ["users"], "1": ["orders"], "2": []},
),
GraphTestCase(
name="multiple tables with hierarchical self-reference patterns",
enabled=HAS_DUCKDB,
code={
"0": "_ = mo.sql(f'CREATE TABLE table_a AS SELECT * FROM db1.table_a')",
"1": "_ = mo.sql(f'CREATE TABLE table_b AS SELECT * FROM db2.table_b')",
"2": "_ = mo.sql(f'SELECT * FROM table_a UNION ALL SELECT * FROM table_b')",
},
expected_parents={"0": [], "1": [], "2": ["0", "1"]},
expected_children={"0": ["2"], "1": ["2"], "2": []},
expected_refs={
"0": ["mo", "db1.table_a"],
"1": ["mo", "db2.table_b"],
"2": ["mo", "table_a", "table_b"],
},
expected_defs={"0": ["table_a"], "1": ["table_b"], "2": []},
),
GraphTestCase(
name="create table from hierarchical ref then reference it hierarchically",
enabled=HAS_DUCKDB,
code={
"0": "_ = mo.sql(f'CREATE SCHEMA my_schema')",
"1": "_ = mo.sql(f'CREATE TABLE my_schema.data AS SELECT * FROM external.my_schema.data')",
"2": "_ = mo.sql(f'SELECT * FROM my_schema.data')",
},
expected_parents={"0": [], "1": ["0"], "2": ["0", "1"]},
expected_children={"0": ["1", "2"], "1": ["2"], "2": []},
expected_refs={
"0": ["mo"],
"1": ["mo", "external.my_schema.data", "my_schema"],
"2": ["mo", "my_schema.data"],
},
expected_defs={"0": ["my_schema"], "1": ["data"], "2": []},
),
GraphTestCase(
name="sql table multiple definitions, different order",
enabled=HAS_DUCKDB,
Expand Down
Loading