risingwavelabs/risingwave · error

inequal condition from the same side should be push down in

Error message

inequal condition from the same side should be push down in optimizer

What it means

get_inequality_desc_from_predicate requires the ASOF join's single inequality condition to reference both left and right sides. An inequality whose operands come from the same side should have been pushed down earlier; encountering one here is rejected with bail! (an error, returned to the caller).

Source

Thrown at src/frontend/src/optimizer/plan_node/logical_join.rs:1581

        let batch_join = BatchHashJoin::new(logical_join, asof_desc);
        Ok(batch_join.into())
    }

    pub fn get_inequality_desc_from_predicate(
        predicate: Condition,
        left_input_len: usize,
    ) -> Result<AsOfJoinDesc> {
        let expr: ExprImpl = predicate.into();
        if let Some((left_input_ref, expr_type, right_input_ref)) = expr.as_comparison_cond() {
            if left_input_ref.index() < left_input_len && right_input_ref.index() >= left_input_len
            {
                Ok(AsOfJoinDesc {
                    left_idx: left_input_ref.index() as u32,
                    right_idx: (right_input_ref.index() - left_input_len) as u32,
                    inequality_type: Self::expr_type_to_comparison_type(expr_type)?.into(),
                })
            } else {
                bail!("inequal condition from the same side should be push down in optimizer");
            }
        } else {
            Err(ErrorCode::InvalidInputSyntax(
                "AsOf join requires exactly 1 ineuquality condition".to_owned(),
            )
            .into())
        }
    }

    fn expr_type_to_comparison_type(expr_type: PbType) -> Result<PbAsOfJoinInequalityType> {
        match expr_type {
            PbType::LessThan => Ok(PbAsOfJoinInequalityType::AsOfInequalityTypeLt),
            PbType::LessThanOrEqual => Ok(PbAsOfJoinInequalityType::AsOfInequalityTypeLe),
            PbType::GreaterThan => Ok(PbAsOfJoinInequalityType::AsOfInequalityTypeGt),
            PbType::GreaterThanOrEqual => Ok(PbAsOfJoinInequalityType::AsOfInequalityTypeGe),
            _ => Err(ErrorCode::InvalidInputSyntax(format!(
                "Invalid comparison type: {}",
                expr_type.as_str_name()

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Move same-side predicates out of the ON clause into a WHERE clause or a subquery filter
  2. Ensure predicate pushdown runs before asof join stream conversion
  3. Keep exactly one left-vs-right inequality condition in the ASOF ON clause
  4. Check the query contains only the required one inequality (error otherwise: 'requires exactly 1 ineuquality condition')

Example fix

-- before
SELECT * FROM t ASOF JOIN d ON t.id = d.id AND t.ts <= d.ts AND t.x < t.y;
-- after
SELECT * FROM (SELECT * FROM t WHERE x < y) t
ASOF JOIN d ON t.id = d.id AND t.ts <= d.ts;
Defensive patterns

Strategy: validation

Validate before calling

// before creating an ASOF join, ensure the ON clause has exactly one cross-side inequality and no same-side predicates:
// same-side comparisons belong in WHERE

Try / catch

match asof_conversion_result { Err(e) if e.to_string().contains("same side") => rewrite_query_with_where_filter(), ... }

Prevention

When it happens

Trigger: ASOF join whose OTHER condition contains a comparison between two columns of the same input side (e.g. `t1.a < t1.b`) instead of a left-right inequality like `t1.ts <= t2.ts`.

Common situations: Users writing ASOF joins with extra same-side predicates in ON; frontend pushdown rules failing to remove them before stream conversion.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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