Skip to main content

laminar_sql/datafusion/json_udf/
mod.rs

1//! PostgreSQL-compatible JSON scalar UDFs (F-SCHEMA-011).
2//!
3//! Implements:
4//!
5//! - **Extraction**: `jsonb_get`, `jsonb_get_idx`, `jsonb_get_text`,
6//!   `jsonb_get_text_idx`, `jsonb_get_path`, `jsonb_get_path_text`
7//! - **Existence**: `jsonb_exists`, `jsonb_exists_any`, `jsonb_exists_all`
8//! - **Containment**: `jsonb_contains`, `jsonb_contained_by`
9//! - **Interrogation**: `json_typeof`
10//! - **Construction**: `json_build_object`, `json_build_array`, `to_jsonb`
11
12mod construction;
13mod extraction;
14mod predicates;
15
16use std::sync::Arc;
17
18use arrow_array::ArrayRef;
19use datafusion_common::Result;
20use datafusion_expr::ColumnarValue;
21
22pub use construction::{JsonBuildArray, JsonBuildObject, JsonTypeof, ToJsonb};
23pub use extraction::{
24    JsonbGet, JsonbGetIdx, JsonbGetPath, JsonbGetPathText, JsonbGetText, JsonbGetTextIdx,
25};
26pub use predicates::{
27    JsonbContainedBy, JsonbContains, JsonbExists, JsonbExistsAll, JsonbExistsAny,
28};
29
30use super::json_types;
31
32// ── Helpers ──────────────────────────────────────────────────────
33
34/// Determine the output length from args (handling scalar/array combos).
35fn output_len(args: &[ColumnarValue]) -> usize {
36    for a in args {
37        if let ColumnarValue::Array(arr) = a {
38            return arr.len();
39        }
40    }
41    1
42}
43
44/// Expand all args to arrays of the same length.
45///
46/// # Errors
47///
48/// Returns a `DataFusionError` if a scalar value cannot be expanded to the target length.
49pub fn expand_args(args: &[ColumnarValue]) -> Result<Vec<ArrayRef>> {
50    let len = output_len(args);
51    args.iter()
52        .map(|a| match a {
53            ColumnarValue::Array(arr) => Ok(Arc::clone(arr)),
54            ColumnarValue::Scalar(s) => s.to_array_of_size(len),
55        })
56        .collect()
57}
58
59#[cfg(test)]
60mod tests;