risingwavelabs/risingwave · error

join plan cannot be generated, tables not connected.

Error message

join plan cannot be generated, tables not connected.

What it means

find_lookup_path builds a join order for a delta join by repeatedly finding a lookup-joinable connection between indexed tables. If, after a step, not all tables have been placed in the path yet but no more joins can be added, the tables are disconnected and no lookup join plan exists.

Source

Thrown at src/frontend/src/optimizer/delta_join_solver.rs:391

            // step 4: place arrangements according to the arrange strategy, update current
            // distribution and current table set.
            for table in &solver_env.arrange_placement_order {
                if let Some(edge) = reachable_tables.get(table) {
                    current_table_set.insert(edge.right);
                    path.push(edge.right);
                    current_distribution.clear();
                    current_distribution.push((edge.right, edge.right_join_key.clone()));
                    continue 'next_table;
                }
            }

            // step 5: no tables can be joined any more, what happened?
            if self.join_order.len() - 1 == path.len() {
                break;
            } else {
                // no table can be joined, while path is still incomplete
                return Err(anyhow!(
                    "join plan cannot be generated, tables not connected."
                ));
            }
        }

        Ok(LookupPath(input_stream, path))
    }

    pub fn solve(&self) -> Result<Vec<LookupPath>> {
        let solver_env = SolverEnv::build_from(self);

        solver_env
            .stream_placement_order
            .iter()
            .map(|x| self.find_lookup_path(&solver_env, *x))
            .collect()
    }

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Create indexes on the join columns of the disconnected tables so lookup joins become possible.
  2. Rewrite the query so tables are connected through indexed equality join predicates.
  3. Remove the intermediate table if it is not needed, or include the connecting table in the query.
  4. Fall back to a standard (non-delta-join) MV plan by not relying on index lookup joins.
Defensive patterns

Strategy: validation

Validate before calling

-- ensure all joined tables have indexes on equality join keys before creating the MV
SELECT name FROM rw_catalog.rw_indexes WHERE ... ;

Try / catch

match create_mv_result {
    Err(e) if e.to_string().contains("tables not connected") => {
        eprintln!("Delta join requires index-connected tables; add missing indexes or rewrite joins");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Creating a materialized view over base tables where some index-connected tables share no join predicates that allow lookup joins, so the delta join solver cannot connect every table in one path (solve -> find_lookup_path).

Common situations: Delta join (index-based MVs) where the query joins tables that are only connected via non-indexed columns or via a third table not included; cross joins or predicates the delta join solver does not recognize.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/d4057d7eae1d9795. Report an issue: GitHub.