uqa-sql 0.5.4

PostgreSQL-compatible SQL compiler built on libpg_query
Documentation
//
// Unified Query Algebra
//
// Copyright (c) 2023-2026 Cognica, Inc.
//

//! JSON extraction resolves both operands before runtime strictness can skip them.

use super::{ExpressionType, Preparation, QueryPlan, RowSchema, SQLError, ScalarExpr};
use uqa_core::Value;

impl Preparation<'_> {
    pub(super) fn json_extraction(
        &mut self,
        symbol: &str,
        arguments: &[ScalarExpr],
        input: &RowSchema,
        subqueries: &[QueryPlan],
    ) -> Result<ExpressionType, SQLError> {
        let [left, right] = arguments else {
            return Err(SQLError::Internal(
                "JSON extraction requires two operands".into(),
            ));
        };
        let mut values = [
            self.expression(left, input, subqueries)?,
            self.expression(right, input, subqueries)?,
        ];
        if values.iter().any(ExpressionType::is_deferred) {
            return Ok(ExpressionType::combined(None, &values));
        }
        let [left, right, result] = crate::type_resolution::named_binary_operator_types(
            symbol,
            values[0].ty.as_ref(),
            values[1].ty.as_ref(),
        )?;
        for ((argument, value), target) in arguments.iter().zip(&mut values).zip([left, right]) {
            let needs_cast = value.ty.as_ref().is_some_and(|source| *source != target)
                || matches!(argument, ScalarExpr::Literal(Value::Null));
            self.parameters.coerce_unknown(value, &target)?;
            if needs_cast {
                self.parameters.retain_input_coercion(argument, target);
            }
        }
        Ok(ExpressionType::combined(Some(result), &values))
    }
}