Skip to main content

uqa_sql/semantics/sets/
static_setness.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Catalog-only set-returning routine classification before physical traversal.
8use super::validation::builtin_returns_set;
9use crate::ast::FunctionBinding;
10
11pub fn function_may_return_set_statically(
12    catalog: &dyn crate::routines::RoutineResolution,
13    name: &str,
14    binding: Option<&FunctionBinding>,
15) -> bool {
16    if binding.and_then(|binding| binding.dispatch).is_some()
17        || binding.is_some_and(FunctionBinding::is_polymorphic_builtin_syntax)
18    {
19        return false;
20    }
21    let identity = name.to_ascii_lowercase();
22    let builtin = crate::semantics::builtin_function_dispatch_name(&identity);
23    if builtin_returns_set(&builtin) || catalog.has_registered_table_function(&identity) {
24        return true;
25    }
26    if binding.is_some_and(|binding| binding.builtin) {
27        return false;
28    }
29    let overloads = match binding {
30        Some(binding) => catalog.lookup_bound_sql_functions_by_binding(binding),
31        None => catalog
32            .lookup_visible_sql_functions_for_analysis(name)
33            .ok()
34            .flatten(),
35    };
36    let Some(overloads) = overloads else {
37        return false;
38    };
39    if let Some(binding) = binding {
40        return overloads.iter().any(|function| {
41            !function.def.is_procedure
42                && crate::routines::routine_signature_types(&function.def) == binding.argument_types
43                && function.def.returns_set()
44        });
45    }
46    overloads
47        .iter()
48        .any(|function| !function.def.is_procedure && function.def.returns_set())
49}