Skip to main content

uqa_sql/semantics/
table_function_arguments.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Argument contracts for analyzer and session table functions.
8
9use crate::SQLError;
10use uqa_core::Value;
11
12pub fn require_no_arguments(name: &str, values: &[Value]) -> Result<(), SQLError> {
13    if values.is_empty() {
14        return Ok(());
15    }
16    Err(SQLError::BadArity {
17        name: name.into(),
18        expected: "0".into(),
19        actual: values.len(),
20    })
21}
22
23pub fn create_analyzer_arguments(evaluated: &[Value]) -> Result<(String, String), SQLError> {
24    if evaluated.len() != 2 {
25        return Err(SQLError::BadArity {
26            name: "create_analyzer".into(),
27            expected: "2".into(),
28            actual: evaluated.len(),
29        });
30    }
31    let analyzer_name = match &evaluated[0] {
32        Value::Str(s) => s.clone(),
33        _ => return Err(SQLError::TypeMismatch("create_analyzer arg 1".into())),
34    };
35    let config_json = match &evaluated[1] {
36        Value::Str(s) => s.clone(),
37        _ => return Err(SQLError::TypeMismatch("create_analyzer arg 2".into())),
38    };
39    Ok((analyzer_name, config_json))
40}
41
42pub fn drop_analyzer_arguments(evaluated: &[Value]) -> Result<String, SQLError> {
43    if evaluated.len() != 1 {
44        return Err(SQLError::BadArity {
45            name: "drop_analyzer".into(),
46            expected: "1".into(),
47            actual: evaluated.len(),
48        });
49    }
50    let analyzer_name = match &evaluated[0] {
51        Value::Str(s) => s.clone(),
52        _ => return Err(SQLError::TypeMismatch("drop_analyzer arg 1".into())),
53    };
54    Ok(analyzer_name)
55}
56
57pub fn analyze_text_arguments(evaluated: &[Value]) -> Result<(String, String), SQLError> {
58    if evaluated.len() != 2 {
59        return Err(SQLError::BadArity {
60            name: "analyze_text".into(),
61            expected: "2".into(),
62            actual: evaluated.len(),
63        });
64    }
65    let name = match &evaluated[0] {
66        Value::Str(value) => value.clone(),
67        _ => return Err(SQLError::TypeMismatch("analyze_text arg 1".into())),
68    };
69    let input = match &evaluated[1] {
70        Value::Str(value) => value.clone(),
71        _ => return Err(SQLError::TypeMismatch("analyze_text arg 2".into())),
72    };
73    Ok((name, input))
74}
75
76pub fn set_table_analyzer_arguments(
77    evaluated: &[Value],
78) -> Result<(String, String, String, String), SQLError> {
79    if !(3..=4).contains(&evaluated.len()) {
80        return Err(SQLError::BadArity {
81            name: "set_table_analyzer".into(),
82            expected: "3 or 4".into(),
83            actual: evaluated.len(),
84        });
85    }
86    let target_table = match &evaluated[0] {
87        Value::Str(s) => s.clone(),
88        _ => return Err(SQLError::TypeMismatch("set_table_analyzer arg 1".into())),
89    };
90    let field = match &evaluated[1] {
91        Value::Str(s) => s.clone(),
92        _ => return Err(SQLError::TypeMismatch("set_table_analyzer arg 2".into())),
93    };
94    let analyzer_name = match &evaluated[2] {
95        Value::Str(s) => s.clone(),
96        _ => return Err(SQLError::TypeMismatch("set_table_analyzer arg 3".into())),
97    };
98    let phase = if evaluated.len() > 3 {
99        match &evaluated[3] {
100            Value::Str(s) => s.clone(),
101            _ => {
102                return Err(SQLError::TypeMismatch(
103                    "set_table_analyzer phase must be a string".into(),
104                ));
105            }
106        }
107    } else {
108        "both".into()
109    };
110    Ok((target_table, field, analyzer_name, phase))
111}
112
113pub fn fts_index_stats_table(evaluated: &[Value]) -> Result<Option<&str>, SQLError> {
114    if evaluated.len() > 1 {
115        return Err(SQLError::TypeMismatch(
116            "fts_index_stats accepts optional table name".into(),
117        ));
118    }
119    let table_filter = match evaluated.first() {
120        Some(Value::Str(s)) => Some(s.as_str()),
121        Some(_) => return Err(SQLError::TypeMismatch("fts_index_stats arg 1".into())),
122        None => None,
123    };
124    Ok(table_filter)
125}