hawk_data/
filter.rs

1use serde_json::Value;
2
3use crate::{Error, apply_stats_operation, print_data_info, string_ops, value_to_string};
4
5pub fn apply_simple_filter(data: Vec<Value>, filter: &str) -> Result<Vec<Value>, Error> {
6    if filter.starts_with("select(") && filter.ends_with(")") {
7        // "select(.age > 30)" から ".age > 30" を抽出
8        let condition = &filter[7..filter.len() - 1];
9
10        // パイプラインがある場合の処理
11        if condition.contains(" | ") {
12            apply_filter_with_string_operations(data, condition)
13        } else {
14            apply_existing_simple_filter(data, condition)
15        }
16    } else {
17        Err(Error::InvalidQuery(format!(
18            "Unsupported filter: {}",
19            filter
20        )))
21    }
22}
23
24/// 文字列操作付きフィルタの適用
25fn apply_filter_with_string_operations(
26    data: Vec<Value>,
27    condition: &str,
28) -> Result<Vec<Value>, Error> {
29    // not演算子のチェック
30    let (condition, is_negated) = parse_not_condition_with_parentheses(condition)?;
31
32    let parts: Vec<&str> = condition.split(" | ").map(|s| s.trim()).collect();
33
34    if parts.len() < 2 {
35        return Err(Error::InvalidQuery("Invalid filter condition".to_string()));
36    }
37
38    let field_access = parts[0];
39    let string_operations: Vec<&str> = parts[1..].to_vec();
40
41    // 最後の操作は比較操作である必要がある
42    let last_operation = string_operations
43        .last()
44        .ok_or_else(|| Error::InvalidQuery("Missing comparison operation".to_string()))?;
45
46    if !is_comparison_operation(last_operation) {
47        return Err(Error::InvalidQuery(
48            "Last operation must be a comparison".to_string(),
49        ));
50    }
51
52    let mut results = Vec::new();
53
54    for item in data {
55        // フィールド値を取得
56        let field_value = extract_field_value(&item, field_access)?;
57
58        // 文字列操作を適用(比較操作まで)
59        let final_value = string_ops::apply_string_pipeline(&field_value, &string_operations)?;
60
61        // 比較結果を評価し、not演算子を適用
62        let condition_result = matches!(final_value, Value::Bool(true));
63        let final_result = if is_negated {
64            !condition_result
65        } else {
66            condition_result
67        };
68
69        if final_result {
70            results.push(item);
71        }
72    }
73
74    Ok(results)
75}
76
77/// 比較操作かどうかを判定
78fn is_comparison_operation(operation: &str) -> bool {
79    let trimmed = operation.trim();
80
81    trimmed.starts_with("contains(")
82        || trimmed.starts_with("starts_with(")
83        || trimmed.starts_with("ends_with(")
84        || trimmed == "=="
85        || trimmed == "!="
86        || trimmed.starts_with("== ")
87        || trimmed.starts_with("!= ")
88}
89
90/// 既存のシンプルフィルタ処理
91fn apply_existing_simple_filter(data: Vec<Value>, condition: &str) -> Result<Vec<Value>, Error> {
92    // not演算子のチェック
93    let (condition, is_negated) = parse_not_condition_with_parentheses(condition)?;
94
95    // 条件をパース
96    let (field_path, operator, value) = parse_condition(&condition)?;
97
98    // フィルタリングを実行
99    let filtered: Vec<Value> = data
100        .into_iter()
101        .filter(|item| {
102            let result = evaluate_condition(item, &field_path, &operator, &value);
103            if is_negated { !result } else { result }
104        })
105        .collect();
106
107    Ok(filtered)
108}
109
110fn parse_not_condition_with_parentheses(condition: &str) -> Result<(String, bool), Error> {
111    let trimmed = condition.trim();
112
113    if trimmed.starts_with("not ") {
114        let rest = trimmed[4..].trim();
115
116        // 括弧で囲まれているかチェック
117        if rest.starts_with('(') && rest.ends_with(')') {
118            let inner_condition = rest[1..rest.len() - 1].trim().to_string();
119            Ok((inner_condition, true))
120        } else {
121            Err(Error::InvalidQuery(
122                "not operator requires parentheses around condition: not (.condition)".to_string(),
123            ))
124        }
125    } else {
126        Ok((trimmed.to_string(), false))
127    }
128}
129
130pub fn apply_pipeline_operation(data: Vec<Value>, operation: &str) -> Result<Vec<Value>, Error> {
131    let trimmed_op = operation.trim();
132
133    if operation.starts_with(".[") && operation.ends_with("]") {
134        return apply_universal_slice_operation(data, operation);
135    }
136
137    if trimmed_op.starts_with("select(") && trimmed_op.ends_with(")") {
138        // フィルタリング操作
139        apply_simple_filter(data, trimmed_op)
140    } else if trimmed_op == "count" {
141        // カウント操作
142        if is_grouped_data(&data) {
143            apply_aggregation_to_groups(data, "count", "")
144        } else {
145            let count = data.len();
146            let count_value = Value::Number(serde_json::Number::from(count));
147            Ok(vec![count_value])
148        }
149    } else if trimmed_op.starts_with("map(") && trimmed_op.ends_with(")") {
150        apply_map_operation(data, trimmed_op)
151    } else if trimmed_op.starts_with("select_fields(") && trimmed_op.ends_with(")") {
152        // 複数フィールド選択
153        let fields_str = &trimmed_op[14..trimmed_op.len() - 1]; // "name,age,department"
154        let field_list: Vec<String> = fields_str
155            .split(',')
156            .map(|s| s.trim().to_string())
157            .collect();
158
159        apply_field_selection(data, field_list)
160    } else if trimmed_op == "info" {
161        // info操作
162        print_data_info(&data);
163        Ok(vec![]) // Return empty vector
164    } else if trimmed_op.starts_with("sum(") && trimmed_op.ends_with(")") {
165        // sum(.field) の処理
166        let field = &trimmed_op[4..trimmed_op.len() - 1];
167        let field_name = field.trim_start_matches('.');
168
169        if is_grouped_data(&data) {
170            apply_aggregation_to_groups(data, "sum", field_name)
171        } else {
172            let sum: f64 = data
173                .iter()
174                .filter_map(|item| item.get(field_name))
175                .filter_map(|val| val.as_f64())
176                .sum();
177
178            let round_sum = if sum.fract() == 0.0 {
179                sum
180            } else {
181                (sum * 10.0).round() / 10.0
182            };
183            let sum_value = Value::Number(serde_json::Number::from_f64(round_sum).unwrap());
184            Ok(vec![sum_value])
185        }
186    } else if trimmed_op.starts_with("avg(") && trimmed_op.ends_with(")") {
187        // avg(.field) の処理
188        let field = &trimmed_op[4..trimmed_op.len() - 1];
189        let field_name = field.trim_start_matches('.');
190
191        if is_grouped_data(&data) {
192            apply_aggregation_to_groups(data, "avg", field_name)
193        } else {
194            let values: Vec<f64> = data
195                .iter()
196                .filter_map(|item| item.get(field_name))
197                .filter_map(|val| val.as_f64())
198                .collect();
199
200            if values.is_empty() {
201                Ok(vec![Value::Null])
202            } else {
203                let avg = values.iter().sum::<f64>() / values.len() as f64;
204                let round_avg = (avg * 10.0).round() / 10.0;
205                let avg_value = Value::Number(serde_json::Number::from_f64(round_avg).unwrap());
206                Ok(vec![avg_value])
207            }
208        }
209    } else if trimmed_op.starts_with("min(") && trimmed_op.ends_with(")") {
210        // min(.field) の処理
211        let field = &trimmed_op[4..trimmed_op.len() - 1];
212        let field_name = field.trim_start_matches('.');
213
214        if is_grouped_data(&data) {
215            apply_aggregation_to_groups(data, "min", field_name)
216        } else {
217            let min_val = data
218                .iter()
219                .filter_map(|item| item.get(field_name))
220                .filter_map(|val| val.as_f64())
221                .fold(f64::INFINITY, f64::min);
222
223            if min_val == f64::INFINITY {
224                Ok(vec![Value::Null])
225            } else {
226                let min_value = Value::Number(serde_json::Number::from_f64(min_val).unwrap());
227                Ok(vec![min_value])
228            }
229        }
230    } else if trimmed_op.starts_with("max(") && trimmed_op.ends_with(")") {
231        // max(.field) の処理
232        let field = &trimmed_op[4..trimmed_op.len() - 1];
233        let field_name = field.trim_start_matches('.');
234
235        if is_grouped_data(&data) {
236            apply_aggregation_to_groups(data, "max", field_name)
237        } else {
238            let max_val = data
239                .iter()
240                .filter_map(|item| item.get(field_name))
241                .filter_map(|val| val.as_f64())
242                .fold(f64::NEG_INFINITY, f64::max);
243
244            if max_val == f64::NEG_INFINITY {
245                Ok(vec![Value::Null])
246            } else {
247                let max_value = Value::Number(serde_json::Number::from_f64(max_val).unwrap());
248                Ok(vec![max_value])
249            }
250        }
251    } else if trimmed_op.starts_with("group_by(") && trimmed_op.ends_with(")") {
252        // group_by(.department) の処理
253        let field = &trimmed_op[9..trimmed_op.len() - 1];
254        let field_name = field.trim_start_matches('.');
255
256        let grouped = group_data_by_field(data, field_name)?;
257        Ok(grouped)
258    } else if trimmed_op == "unique" {
259        // unique操作(重複除去)
260        let result = apply_stats_operation(&data, "unique", None)?;
261        if let Value::Array(arr) = result {
262            Ok(arr)
263        } else {
264            Ok(vec![result])
265        }
266    } else if trimmed_op == "sort" {
267        // sort操作
268        let result = apply_stats_operation(&data, "sort", None)?;
269        if let Value::Array(arr) = result {
270            Ok(arr)
271        } else {
272            Ok(vec![result])
273        }
274    } else if trimmed_op == "length" {
275        // length操作(配列の長さ)
276        let result = apply_stats_operation(&data, "length", None)?;
277        Ok(vec![result])
278    } else if trimmed_op == "median" {
279        // median操作(中央値)
280        let result = apply_stats_operation(&data, "median", None)?;
281        Ok(vec![result])
282    } else if trimmed_op == "stddev" {
283        // stddev操作(標準偏差)
284        let result = apply_stats_operation(&data, "stddev", None)?;
285        Ok(vec![result])
286    } else if trimmed_op.starts_with("unique(") && trimmed_op.ends_with(")") {
287        // unique(.field) - フィールド指定
288        let field = &trimmed_op[7..trimmed_op.len() - 1];
289        let field_name = field.trim_start_matches('.');
290        let result = apply_stats_operation(&data, "unique", Some(field_name))?;
291        if let Value::Array(arr) = result {
292            Ok(arr)
293        } else {
294            Ok(vec![result])
295        }
296    } else if trimmed_op.starts_with("sort(") && trimmed_op.ends_with(")") {
297        // sort(.field) - フィールド指定
298        let field = &trimmed_op[5..trimmed_op.len() - 1];
299        let field_name = field.trim_start_matches('.');
300        let result = apply_stats_operation(&data, "sort", Some(field_name))?;
301        if let Value::Array(arr) = result {
302            Ok(arr)
303        } else {
304            Ok(vec![result])
305        }
306    } else if trimmed_op.starts_with("median(") && trimmed_op.ends_with(")") {
307        // median(.field) - フィールド指定
308        let field = &trimmed_op[7..trimmed_op.len() - 1];
309        let field_name = field.trim_start_matches('.');
310        let result = apply_stats_operation(&data, "median", Some(field_name))?;
311        Ok(vec![result])
312    } else if trimmed_op.starts_with("stddev(") && trimmed_op.ends_with(")") {
313        // stddev(.field) - フィールド指定
314        let field = &trimmed_op[7..trimmed_op.len() - 1];
315        let field_name = field.trim_start_matches('.');
316        let result = apply_stats_operation(&data, "stddev", Some(field_name))?;
317        Ok(vec![result])
318    } else {
319        // より詳細なエラーメッセージ
320        Err(Error::InvalidQuery(format!(
321            "Unsupported operation: '{}' (length: {}, starts with 'map(': {}, ends with ')': {})",
322            trimmed_op,
323            trimmed_op.len(),
324            trimmed_op.starts_with("map("),
325            trimmed_op.ends_with(")")
326        )))
327    }
328}
329
330/// map操作の実装
331fn apply_map_operation(data: Vec<Value>, operation: &str) -> Result<Vec<Value>, Error> {
332    // "map(.field | string_operation)" または "map(.field1, .field2 | operation)" の解析
333    let content = &operation[4..operation.len() - 1]; // "map(" と ")" を除去
334
335    // **新機能: 複数フィールド対応**
336    if content.contains(',') && content.contains('|') {
337        // 複数フィールドの場合: "map(.skills, .projects | join(\",\"))"
338        apply_multi_field_map_operation(data, content)
339    } else {
340        // 単一フィールドの場合: "map(.field | operation)"
341        apply_single_field_map_operation(data, content)
342    }
343}
344
345/// 単一フィールドのmap操作(既存)
346fn apply_single_field_map_operation(data: Vec<Value>, content: &str) -> Result<Vec<Value>, Error> {
347    let (field_access, string_operations) = parse_map_content(content)?;
348
349    let mut results = Vec::new();
350
351    for item in data {
352        // フィールドにアクセス
353        let field_value = extract_field_value(&item, &field_access)?;
354
355        // 文字列操作を適用
356        let transformed_value = apply_string_operations(&field_value, &string_operations)?;
357
358        // 元のオブジェクトを更新または新しい値を作成
359        let result = update_or_create_value(&item, &field_access, transformed_value)?;
360        results.push(result);
361    }
362
363    Ok(results)
364}
365
366/// 複数フィールドのmap操作(ケース1: 各フィールドに同じ操作)
367fn apply_multi_field_map_operation(data: Vec<Value>, content: &str) -> Result<Vec<Value>, Error> {
368    // "(.skills, .projects | join(\",\"))" を解析
369    let parts: Vec<&str> = content.split('|').map(|s| s.trim()).collect();
370
371    if parts.len() != 2 {
372        return Err(Error::InvalidQuery(
373            "Multi-field map must have format: (.field1, .field2 | operation)".to_string(),
374        ));
375    }
376
377    let fields_part = parts[0].trim();
378    let operation = parts[1].trim();
379
380    // フィールド部分をパース: ".skills, .projects"
381    let field_paths: Vec<&str> = fields_part.split(',').map(|s| s.trim()).collect();
382
383    // 各フィールドパスが "." で始まることを確認
384    for field_path in &field_paths {
385        if !field_path.starts_with('.') {
386            return Err(Error::InvalidQuery(format!(
387                "Field path must start with '.': {}",
388                field_path
389            )));
390        }
391    }
392
393    let mut results = Vec::new();
394
395    for item in data {
396        // 各フィールドに同じ操作を適用(ケース1)
397        let transformed_item =
398            crate::string_ops::apply_operation_to_multiple_fields(&item, &field_paths, operation)?;
399        results.push(transformed_item);
400    }
401
402    Ok(results)
403}
404
405/// map操作の内容を解析(例: ".name | upper | trim")
406fn parse_map_content(content: &str) -> Result<(String, Vec<String>), Error> {
407    let parts: Vec<&str> = content.split('|').map(|s| s.trim()).collect();
408
409    if parts.is_empty() {
410        return Err(Error::InvalidQuery("Empty map operation".to_string()));
411    }
412
413    // 最初の部分はフィールドアクセス
414    let field_access = parts[0].to_string();
415
416    // 残りは文字列操作
417    let string_operations: Vec<String> = parts[1..].iter().map(|s| s.to_string()).collect();
418
419    Ok((field_access, string_operations))
420}
421
422/// フィールド値を抽出
423fn extract_field_value(item: &Value, field_access: &str) -> Result<Value, Error> {
424    if field_access == "." {
425        // ルート値(Text配列の場合の各行)
426        return Ok(item.clone());
427    }
428
429    if field_access.starts_with('.') {
430        let field_name = &field_access[1..]; // '.' を除去
431
432        if let Some(value) = item.get(field_name) {
433            Ok(value.clone())
434        } else {
435            Err(Error::InvalidQuery(format!(
436                "Field '{}' not found",
437                field_name
438            )))
439        }
440    } else {
441        Err(Error::InvalidQuery(format!(
442            "Invalid field access: {}",
443            field_access
444        )))
445    }
446}
447
448/// 文字列操作を順次適用
449fn apply_string_operations(value: &Value, operations: &[String]) -> Result<Value, Error> {
450    if operations.is_empty() {
451        return Ok(value.clone());
452    }
453
454    let operations_str: Vec<&str> = operations.iter().map(|s| s.as_str()).collect();
455    string_ops::apply_string_pipeline(value, &operations_str)
456}
457
458/// 値を更新または新しい値を作成
459fn update_or_create_value(
460    original: &Value,
461    field_access: &str,
462    new_value: Value,
463) -> Result<Value, Error> {
464    if field_access == "." {
465        // ルート値の場合は直接置き換え
466        Ok(new_value)
467    } else if field_access.starts_with('.') {
468        let field_name = &field_access[1..];
469
470        // オブジェクトの場合はフィールドを更新
471        if let Value::Object(mut obj) = original.clone() {
472            obj.insert(field_name.to_string(), new_value);
473            Ok(Value::Object(obj))
474        } else {
475            // オブジェクトでない場合は新しいオブジェクトを作成
476            let mut new_obj = serde_json::Map::new();
477            new_obj.insert(field_name.to_string(), new_value);
478            Ok(Value::Object(new_obj))
479        }
480    } else {
481        Err(Error::InvalidQuery(format!(
482            "Invalid field access: {}",
483            field_access
484        )))
485    }
486}
487
488fn apply_field_selection(data: Vec<Value>, field_list: Vec<String>) -> Result<Vec<Value>, Error> {
489    let mut results = Vec::new();
490
491    for item in data {
492        if let Value::Object(obj) = item {
493            let mut selected_obj = serde_json::Map::new();
494
495            // 指定されたフィールドのみを抽出
496            for field_name in &field_list {
497                if let Some(value) = obj.get(field_name) {
498                    selected_obj.insert(field_name.clone(), value.clone());
499                }
500            }
501
502            results.push(Value::Object(selected_obj));
503        } else {
504            // オブジェクト以外は無視するか、エラーにする
505            return Err(Error::InvalidQuery(
506                "select_fields can only be applied to objects".into(),
507            ));
508        }
509    }
510
511    Ok(results)
512}
513
514fn group_data_by_field(data: Vec<Value>, field_name: &str) -> Result<Vec<Value>, Error> {
515    use std::collections::HashMap;
516
517    let mut groups: HashMap<String, Vec<Value>> = HashMap::new();
518
519    // データをフィールド値でグルーピング
520    for item in data {
521        if let Some(field_value) = item.get(field_name) {
522            let key = value_to_string(field_value);
523            groups.entry(key).or_default().push(item);
524        }
525    }
526
527    // グループを配列として返す
528    let result: Vec<Value> = groups
529        .into_iter()
530        .map(|(group_name, group_items)| {
531            let mut group_obj = serde_json::Map::new();
532            group_obj.insert("group".to_string(), Value::String(group_name));
533            group_obj.insert("items".to_string(), Value::Array(group_items));
534            Value::Object(group_obj)
535        })
536        .collect();
537
538    Ok(result)
539}
540
541fn parse_condition(condition: &str) -> Result<(String, String, String), Error> {
542    let condition = condition.trim();
543
544    // 演算子を検出
545    if let Some(pos) = condition.find(" >= ") {
546        let field = condition[..pos].trim().to_string();
547        let value = condition[pos + 4..].trim().to_string();
548        return Ok((field, ">=".to_string(), value));
549    }
550
551    if let Some(pos) = condition.find(" <= ") {
552        let field = condition[..pos].trim().to_string();
553        let value = condition[pos + 4..].trim().to_string();
554        return Ok((field, "<=".to_string(), value));
555    }
556
557    if let Some(pos) = condition.find(" > ") {
558        let field = condition[..pos].trim().to_string();
559        let value = condition[pos + 3..].trim().to_string();
560        return Ok((field, ">".to_string(), value));
561    }
562
563    if let Some(pos) = condition.find(" < ") {
564        let field = condition[..pos].trim().to_string();
565        let value = condition[pos + 3..].trim().to_string();
566        return Ok((field, "<".to_string(), value));
567    }
568
569    if let Some(pos) = condition.find(" == ") {
570        let field = condition[..pos].trim().to_string();
571        let value = condition[pos + 4..].trim().to_string();
572        return Ok((field, "==".to_string(), value));
573    }
574
575    if let Some(pos) = condition.find(" != ") {
576        let field = condition[..pos].trim().to_string();
577        let value = condition[pos + 4..].trim().to_string();
578        return Ok((field, "!=".to_string(), value));
579    }
580
581    Err(Error::InvalidQuery("Invalid condition format".into()))
582}
583
584fn evaluate_condition(item: &Value, field_path: &str, operator: &str, value: &str) -> bool {
585    // フィールドパスから値を取得 (.age -> age)
586    let field_name = if field_path.starts_with('.') {
587        &field_path[1..]
588    } else {
589        field_path
590    };
591
592    let field_value = match item.get(field_name) {
593        Some(val) => val,
594        None => return false,
595    };
596
597    match operator {
598        ">" => compare_greater(field_value, value),
599        "<" => compare_less(field_value, value),
600        ">=" => compare_greater_equal(field_value, value),
601        "<=" => compare_less_equal(field_value, value),
602        "==" => compare_equal(field_value, value),
603        "!=" => !compare_equal(field_value, value),
604        _ => false,
605    }
606}
607
608fn compare_greater(field_value: &Value, target: &str) -> bool {
609    match field_value {
610        Value::Number(n) => {
611            if let Ok(target_num) = target.parse::<f64>() {
612                n.as_f64().unwrap_or(0.0) > target_num
613            } else {
614                false
615            }
616        }
617        _ => false,
618    }
619}
620
621fn compare_less(field_value: &Value, target: &str) -> bool {
622    match field_value {
623        Value::Number(n) => {
624            if let Ok(target_num) = target.parse::<f64>() {
625                n.as_f64().unwrap_or(0.0) < target_num
626            } else {
627                false
628            }
629        }
630        _ => false,
631    }
632}
633
634fn compare_equal(field_value: &Value, target: &str) -> bool {
635    match field_value {
636        Value::String(s) => {
637            // 文字列比較(引用符を除去)
638            let target_clean = target.trim_matches('"');
639            s == target_clean
640        }
641        Value::Number(n) => {
642            if let Ok(target_num) = target.parse::<f64>() {
643                n.as_f64().unwrap_or(0.0) == target_num
644            } else {
645                false
646            }
647        }
648        Value::Bool(b) => match target {
649            "true" => *b,
650            "false" => !*b,
651            _ => false,
652        },
653        _ => false,
654    }
655}
656
657fn compare_greater_equal(field_value: &Value, target: &str) -> bool {
658    match field_value {
659        Value::Number(n) => {
660            if let Ok(target_num) = target.parse::<f64>() {
661                n.as_f64().unwrap_or(0.0) >= target_num
662            } else {
663                false
664            }
665        }
666        _ => false,
667    }
668}
669
670fn compare_less_equal(field_value: &Value, target: &str) -> bool {
671    match field_value {
672        Value::Number(n) => {
673            if let Ok(target_num) = target.parse::<f64>() {
674                n.as_f64().unwrap_or(0.0) <= target_num
675            } else {
676                false
677            }
678        }
679        _ => false,
680    }
681}
682
683fn is_grouped_data(data: &[Value]) -> bool {
684    data.iter().all(|item| {
685        if let Value::Object(obj) = item {
686            obj.contains_key("group") && obj.contains_key("items")
687        } else {
688            false
689        }
690    })
691}
692
693fn apply_aggregation_to_groups(
694    data: Vec<Value>,
695    operation: &str,
696    field_name: &str,
697) -> Result<Vec<Value>, Error> {
698    let mut results = Vec::new();
699
700    for group_data in data {
701        if let Value::Object(group_obj) = group_data {
702            let group_name = group_obj.get("group").unwrap();
703            let items = group_obj.get("items").and_then(|v| v.as_array()).unwrap();
704
705            // 各グループのitemsに対して集約を実行
706            let aggregated_value = match operation {
707                "avg" => calculate_avg(items, field_name)?,
708                "sum" => calculate_sum(items, field_name)?,
709                "count" => Value::Number(serde_json::Number::from(items.len())),
710                "min" => calculate_min(items, field_name)?,
711                "max" => calculate_max(items, field_name)?,
712                _ => Value::Null,
713            };
714
715            // 結果オブジェクトを作成
716            let mut result_obj = serde_json::Map::new();
717            result_obj.insert("group".to_string(), group_name.clone());
718            result_obj.insert(operation.to_string(), aggregated_value);
719            results.push(Value::Object(result_obj));
720        }
721    }
722
723    Ok(results)
724}
725
726fn calculate_avg(items: &[Value], field_name: &str) -> Result<Value, Error> {
727    let values: Vec<f64> = items
728        .iter()
729        .filter_map(|item| item.get(field_name))
730        .filter_map(|val| val.as_f64())
731        .collect();
732
733    if values.is_empty() {
734        Ok(Value::Null)
735    } else {
736        let avg = values.iter().sum::<f64>() / values.len() as f64;
737        let rounded_avg = (avg * 10.0).round() / 10.0;
738        Ok(Value::Number(
739            serde_json::Number::from_f64(rounded_avg).unwrap(),
740        ))
741    }
742}
743
744fn calculate_sum(items: &[Value], field_name: &str) -> Result<Value, Error> {
745    let sum: f64 = items
746        .iter()
747        .filter_map(|item| item.get(field_name))
748        .filter_map(|val| val.as_f64())
749        .sum();
750
751    let rounded_sum = if sum.fract() == 0.0 {
752        sum
753    } else {
754        (sum * 10.0).round() / 10.0
755    };
756
757    Ok(Value::Number(
758        serde_json::Number::from_f64(rounded_sum).unwrap(),
759    ))
760}
761
762fn calculate_min(items: &[Value], field_name: &str) -> Result<Value, Error> {
763    let min_val = items
764        .iter()
765        .filter_map(|item| item.get(field_name))
766        .filter_map(|val| val.as_f64())
767        .fold(f64::INFINITY, f64::min);
768
769    if min_val == f64::INFINITY {
770        Ok(Value::Null)
771    } else {
772        Ok(Value::Number(
773            serde_json::Number::from_f64(min_val).unwrap(),
774        ))
775    }
776}
777
778fn calculate_max(items: &[Value], field_name: &str) -> Result<Value, Error> {
779    let max_val = items
780        .iter()
781        .filter_map(|item| item.get(field_name))
782        .filter_map(|val| val.as_f64())
783        .fold(f64::NEG_INFINITY, f64::max);
784
785    if max_val == f64::NEG_INFINITY {
786        Ok(Value::Null)
787    } else {
788        Ok(Value::Number(
789            serde_json::Number::from_f64(max_val).unwrap(),
790        ))
791    }
792}
793
794/// 配列に対してスライス操作を適用(汎用関数)
795pub fn apply_array_slice(array: &[Value], start: Option<usize>, end: Option<usize>) -> Vec<Value> {
796    let len = array.len();
797
798    let start_idx = start.unwrap_or(0);
799    let end_idx = end.unwrap_or(len);
800
801    // 範囲チェック
802    let start_idx = start_idx.min(len);
803    let end_idx = end_idx.min(len);
804
805    if start_idx >= end_idx {
806        return Vec::new(); // 無効な範囲の場合は空を返す
807    }
808
809    array[start_idx..end_idx].to_vec()
810}
811
812/// グループ化されたデータに対してスライスを適用
813pub fn apply_slice_to_grouped_data(
814    data: Vec<Value>,
815    start: Option<usize>,
816    end: Option<usize>,
817) -> Result<Vec<Value>, Error> {
818    let mut result = Vec::new();
819
820    for group in data {
821        if let Value::Array(group_items) = group {
822            // 各グループに対してスライスを適用
823            let sliced_group = apply_array_slice(&group_items, start, end);
824
825            // スライス結果を展開して結果に追加
826            result.extend(sliced_group);
827        } else {
828            // 配列でない場合はそのまま追加(エラー回避)
829            result.push(group);
830        }
831    }
832
833    Ok(result)
834}
835
836/// スライス記法をパース ([start:end] 形式)
837pub fn parse_slice_notation(
838    bracket_content: &str,
839) -> Result<(Option<usize>, Option<usize>), Error> {
840    if !bracket_content.contains(':') {
841        return Err(Error::InvalidQuery("Not a slice notation".to_string()));
842    }
843
844    let parts: Vec<&str> = bracket_content.split(':').collect();
845    if parts.len() != 2 {
846        return Err(Error::InvalidQuery(
847            "Invalid slice format, expected start:end".to_string(),
848        ));
849    }
850
851    let start = if parts[0].is_empty() {
852        None // 空の場合は先頭から
853    } else {
854        Some(
855            parts[0]
856                .parse::<usize>()
857                .map_err(|_| Error::InvalidQuery(format!("Invalid start index: {}", parts[0])))?,
858        )
859    };
860
861    let end = if parts[1].is_empty() {
862        None // 空の場合は末尾まで
863    } else {
864        Some(
865            parts[1]
866                .parse::<usize>()
867                .map_err(|_| Error::InvalidQuery(format!("Invalid end index: {}", parts[1])))?,
868        )
869    };
870
871    Ok((start, end))
872}
873
874/// 負のインデックスに対応したスライス解析
875pub fn parse_slice_notation_with_negative(
876    bracket_content: &str,
877    data_len: usize,
878) -> Result<(Option<usize>, Option<usize>), Error> {
879    let parts: Vec<&str> = bracket_content.split(':').collect();
880    if parts.len() != 2 {
881        return Err(Error::InvalidQuery(
882            "Invalid slice format, expected start:end".to_string(),
883        ));
884    }
885
886    let start = if parts[0].is_empty() {
887        None
888    } else {
889        Some(parse_index_with_negative(parts[0], data_len)?)
890    };
891
892    let end = if parts[1].is_empty() {
893        None
894    } else {
895        Some(parse_index_with_negative(parts[1], data_len)?)
896    };
897
898    Ok((start, end))
899}
900
901/// 負のインデックス対応のインデックス解析
902pub fn parse_index_with_negative(index_str: &str, data_len: usize) -> Result<usize, Error> {
903    if index_str.starts_with('-') {
904        let negative_index = index_str[1..]
905            .parse::<usize>()
906            .map_err(|_| Error::InvalidQuery(format!("Invalid negative index: {}", index_str)))?;
907
908        if negative_index > data_len {
909            Ok(0) // 範囲外の場合は0に
910        } else {
911            Ok(data_len - negative_index)
912        }
913    } else {
914        index_str
915            .parse::<usize>()
916            .map_err(|_| Error::InvalidQuery(format!("Invalid index: {}", index_str)))
917    }
918}
919
920/// データ構造の種類を判定
921#[derive(Debug, PartialEq)]
922pub enum DataStructure {
923    GroupedData,  // group_by後:全て配列
924    RegularArray, // 通常の配列:オブジェクトや値の配列
925    NestedArrays, // ネストした配列:配列の配列(group_byではない)
926    Mixed,        // 混合
927}
928
929pub fn detect_data_structure(data: &[Value]) -> DataStructure {
930    if data.is_empty() {
931        return DataStructure::RegularArray;
932    }
933
934    let all_arrays = data.iter().all(|item| item.is_array());
935    let all_objects = data.iter().all(|item| item.is_object());
936    let all_primitives = data.iter().all(|item| {
937        matches!(
938            item,
939            Value::String(_) | Value::Number(_) | Value::Bool(_) | Value::Null
940        )
941    });
942
943    if all_arrays {
944        // 全て配列の場合、group_byの結果かネストした配列かを判定
945        if is_likely_grouped_data(data) {
946            DataStructure::GroupedData
947        } else {
948            DataStructure::NestedArrays
949        }
950    } else if all_objects || all_primitives {
951        DataStructure::RegularArray
952    } else {
953        DataStructure::Mixed
954    }
955}
956
957/// group_byの結果らしいデータかを判定
958pub fn is_likely_grouped_data(data: &[Value]) -> bool {
959    // 簡単なヒューリスティック:
960    // 1. 全て配列
961    // 2. 各配列が空でない
962    // 3. 各配列の最初の要素が同じ構造(オブジェクト)
963
964    if data.len() < 2 {
965        return false; // グループが1個だけの場合は判定困難
966    }
967
968    for item in data {
969        if let Value::Array(arr) = item {
970            if arr.is_empty() {
971                return false;
972            }
973            if !arr[0].is_object() {
974                return false;
975            }
976        } else {
977            return false;
978        }
979    }
980
981    true
982}
983
984/// ユニバーサルスライス操作(あらゆるデータに対応)
985pub fn apply_universal_slice_operation(
986    data: Vec<Value>,
987    operation: &str,
988) -> Result<Vec<Value>, Error> {
989    let bracket_content = &operation[2..operation.len() - 1]; // ".["と"]"を除去
990
991    // 負のインデックス対応の確認
992    if bracket_content.starts_with('-') && !bracket_content.contains(':') {
993        return apply_negative_index_slice(data, bracket_content);
994    }
995
996    // 通常のスライス記法かどうかチェック
997    if !bracket_content.contains(':') {
998        // 単一インデックスの場合
999        let index = bracket_content
1000            .parse::<usize>()
1001            .map_err(|_| Error::InvalidQuery(format!("Invalid index: {}", bracket_content)))?;
1002
1003        if let Some(item) = data.get(index) {
1004            return Ok(vec![item.clone()]);
1005        } else {
1006            return Ok(vec![]); // インデックスが範囲外の場合は空を返す
1007        }
1008    }
1009
1010    // スライス記法の解析
1011    let (start, end) = parse_slice_notation_with_negative(bracket_content, data.len())?;
1012
1013    // データ構造に応じた適切な処理
1014    match detect_data_structure(&data) {
1015        DataStructure::GroupedData => apply_slice_to_grouped_data(data, start, end),
1016        DataStructure::RegularArray => apply_slice_to_regular_array(data, start, end),
1017        DataStructure::NestedArrays => apply_slice_to_nested_arrays(data, start, end),
1018        DataStructure::Mixed => apply_slice_to_regular_array(data, start, end), // デフォルト
1019    }
1020}
1021
1022/// 負のインデックス単体の処理
1023pub fn apply_negative_index_slice(data: Vec<Value>, index_str: &str) -> Result<Vec<Value>, Error> {
1024    let data_len = data.len();
1025    let negative_index = index_str[1..]
1026        .parse::<usize>()
1027        .map_err(|_| Error::InvalidQuery(format!("Invalid negative index: {}", index_str)))?;
1028
1029    if negative_index > data_len || negative_index == 0 {
1030        return Ok(vec![]); // 範囲外または-0の場合
1031    }
1032
1033    let actual_index = data_len - negative_index;
1034    if let Some(item) = data.get(actual_index) {
1035        Ok(vec![item.clone()])
1036    } else {
1037        Ok(vec![])
1038    }
1039}
1040
1041/// 通常の配列に対するスライス
1042pub fn apply_slice_to_regular_array(
1043    data: Vec<Value>,
1044    start: Option<usize>,
1045    end: Option<usize>,
1046) -> Result<Vec<Value>, Error> {
1047    let sliced = apply_array_slice(&data, start, end);
1048    Ok(sliced)
1049}
1050
1051/// ネストした配列に対するスライス
1052pub fn apply_slice_to_nested_arrays(
1053    data: Vec<Value>,
1054    start: Option<usize>,
1055    end: Option<usize>,
1056) -> Result<Vec<Value>, Error> {
1057    // ネストした配列の場合、外側の配列をスライスする(より直感的)
1058    let sliced = apply_array_slice(&data, start, end);
1059    Ok(sliced)
1060}
1061
1062/// フィールド指定ソート操作
1063pub fn apply_sort_with_field_operation(
1064    data: Vec<Value>,
1065    operation: &str,
1066) -> Result<Vec<Value>, Error> {
1067    let field_path = &operation[5..operation.len() - 1]; // "sort(" と ")" を除去
1068
1069    let mut sorted_data = data;
1070    sorted_data.sort_by(|a, b| {
1071        let value_a = extract_sort_key(a, field_path);
1072        let value_b = extract_sort_key(b, field_path);
1073
1074        compare_sort_values(&value_a, &value_b)
1075    });
1076
1077    Ok(sorted_data)
1078}
1079
1080/// ソート用のキー値を抽出
1081pub fn extract_sort_key(item: &Value, field_path: &str) -> Value {
1082    if field_path.starts_with('.') {
1083        let field_name = &field_path[1..];
1084        item.get(field_name).cloned().unwrap_or(Value::Null)
1085    } else {
1086        item.clone()
1087    }
1088}
1089
1090/// ソート用の値比較
1091pub fn compare_sort_values(a: &Value, b: &Value) -> std::cmp::Ordering {
1092    use std::cmp::Ordering;
1093
1094    match (a, b) {
1095        (Value::Number(n1), Value::Number(n2)) => {
1096            let f1 = n1.as_f64().unwrap_or(0.0);
1097            let f2 = n2.as_f64().unwrap_or(0.0);
1098            f1.partial_cmp(&f2).unwrap_or(Ordering::Equal)
1099        }
1100        (Value::String(s1), Value::String(s2)) => s1.cmp(s2),
1101        (Value::Bool(b1), Value::Bool(b2)) => b1.cmp(b2),
1102        (Value::Null, Value::Null) => Ordering::Equal,
1103        (Value::Null, _) => Ordering::Less,
1104        (_, Value::Null) => Ordering::Greater,
1105        _ => Ordering::Equal,
1106    }
1107}
1108
1109#[cfg(test)]
1110mod tests {
1111    use super::*;
1112    use serde_json::json;
1113
1114    #[test]
1115    fn test_apply_array_slice_basic() {
1116        let array = vec![json!("a"), json!("b"), json!("c"), json!("d"), json!("e")];
1117
1118        // [0:3] -> ["a", "b", "c"]
1119        let result = apply_array_slice(&array, Some(0), Some(3));
1120        assert_eq!(result.len(), 3);
1121        assert_eq!(result[0], json!("a"));
1122        assert_eq!(result[2], json!("c"));
1123
1124        // [1:4] -> ["b", "c", "d"]
1125        let result = apply_array_slice(&array, Some(1), Some(4));
1126        assert_eq!(result.len(), 3);
1127        assert_eq!(result[0], json!("b"));
1128
1129        // [:3] -> ["a", "b", "c"]
1130        let result = apply_array_slice(&array, None, Some(3));
1131        assert_eq!(result.len(), 3);
1132        assert_eq!(result[0], json!("a"));
1133
1134        // [2:] -> ["c", "d", "e"]
1135        let result = apply_array_slice(&array, Some(2), None);
1136        assert_eq!(result.len(), 3);
1137        assert_eq!(result[0], json!("c"));
1138
1139        // 範囲外の場合
1140        let result = apply_array_slice(&array, Some(10), Some(20));
1141        assert_eq!(result.len(), 0);
1142
1143        // 無効な範囲
1144        let result = apply_array_slice(&array, Some(3), Some(1));
1145        assert_eq!(result.len(), 0);
1146    }
1147
1148    #[test]
1149    fn test_apply_slice_to_grouped_data() {
1150        // group_by後のデータ形式をシミュレート
1151        let grouped_data = vec![
1152            json!([
1153                {"category": "Electronics", "name": "Laptop", "price": 1200},
1154                {"category": "Electronics", "name": "Phone", "price": 800},
1155                {"category": "Electronics", "name": "Tablet", "price": 600},
1156                {"category": "Electronics", "name": "Mouse", "price": 25}
1157            ]),
1158            json!([
1159                {"category": "Books", "name": "Fiction", "price": 20},
1160                {"category": "Books", "name": "Science", "price": 30},
1161                {"category": "Books", "name": "History", "price": 25},
1162                {"category": "Books", "name": "Biography", "price": 35}
1163            ]),
1164            json!([
1165                {"category": "Clothing", "name": "Shirt", "price": 40},
1166                {"category": "Clothing", "name": "Pants", "price": 60},
1167                {"category": "Clothing", "name": "Shoes", "price": 80}
1168            ]),
1169        ];
1170
1171        // 各グループから最初の2個を取得
1172        let result = apply_slice_to_grouped_data(grouped_data.clone(), Some(0), Some(2)).unwrap();
1173
1174        // 結果の検証:3グループ × 2個 = 6個
1175        assert_eq!(result.len(), 6);
1176
1177        // Electronics グループの最初の2個
1178        assert_eq!(result[0].get("name").unwrap(), &json!("Laptop"));
1179        assert_eq!(result[1].get("name").unwrap(), &json!("Phone"));
1180
1181        // Books グループの最初の2個
1182        assert_eq!(result[2].get("name").unwrap(), &json!("Fiction"));
1183        assert_eq!(result[3].get("name").unwrap(), &json!("Science"));
1184
1185        // Clothing グループの最初の2個
1186        assert_eq!(result[4].get("name").unwrap(), &json!("Shirt"));
1187        assert_eq!(result[5].get("name").unwrap(), &json!("Pants"));
1188    }
1189
1190    #[test]
1191    fn test_apply_slice_to_grouped_data_different_ranges() {
1192        let grouped_data = vec![
1193            json!([
1194                {"id": 1, "group": "A"},
1195                {"id": 2, "group": "A"},
1196                {"id": 3, "group": "A"},
1197                {"id": 4, "group": "A"},
1198                {"id": 5, "group": "A"}
1199            ]),
1200            json!([
1201                {"id": 6, "group": "B"},
1202                {"id": 7, "group": "B"},
1203                {"id": 8, "group": "B"},
1204                {"id": 9, "group": "B"}
1205            ]),
1206        ];
1207
1208        // 各グループから2番目から4番目まで(インデックス1-3)
1209        let result = apply_slice_to_grouped_data(grouped_data.clone(), Some(1), Some(4)).unwrap();
1210
1211        // A群:3個(id: 2,3,4)、B群:3個(id: 7,8,9)= 合計6個
1212        assert_eq!(result.len(), 6);
1213
1214        // A群の結果確認
1215        assert_eq!(result[0].get("id").unwrap(), &json!(2));
1216        assert_eq!(result[1].get("id").unwrap(), &json!(3));
1217        assert_eq!(result[2].get("id").unwrap(), &json!(4));
1218
1219        // B群の結果確認
1220        assert_eq!(result[3].get("id").unwrap(), &json!(7));
1221        assert_eq!(result[4].get("id").unwrap(), &json!(8));
1222        assert_eq!(result[5].get("id").unwrap(), &json!(9));
1223    }
1224
1225    #[test]
1226    fn test_parse_slice_notation() {
1227        // 通常のスライス
1228        let (start, end) = parse_slice_notation("0:5").unwrap();
1229        assert_eq!(start, Some(0));
1230        assert_eq!(end, Some(5));
1231
1232        // 開始インデックスなし
1233        let (start, end) = parse_slice_notation(":5").unwrap();
1234        assert_eq!(start, None);
1235        assert_eq!(end, Some(5));
1236
1237        // 終了インデックスなし
1238        let (start, end) = parse_slice_notation("2:").unwrap();
1239        assert_eq!(start, Some(2));
1240        assert_eq!(end, None);
1241
1242        // 両方なし(全体)
1243        let (start, end) = parse_slice_notation(":").unwrap();
1244        assert_eq!(start, None);
1245        assert_eq!(end, None);
1246
1247        // エラーケース
1248        assert!(parse_slice_notation("abc:def").is_err());
1249        assert!(parse_slice_notation("0:5:10").is_err());
1250    }
1251
1252    #[test]
1253    fn test_parse_index_with_negative() {
1254        // 正のインデックス
1255        assert_eq!(parse_index_with_negative("5", 10).unwrap(), 5);
1256
1257        // 負のインデックス
1258        assert_eq!(parse_index_with_negative("-1", 10).unwrap(), 9);
1259        assert_eq!(parse_index_with_negative("-3", 10).unwrap(), 7);
1260
1261        // 範囲外の負のインデックス
1262        assert_eq!(parse_index_with_negative("-15", 10).unwrap(), 0);
1263
1264        // エラーケース
1265        assert!(parse_index_with_negative("abc", 10).is_err());
1266        assert!(parse_index_with_negative("-abc", 10).is_err());
1267    }
1268
1269    #[test]
1270    fn test_detect_data_structure() {
1271        // 通常の配列
1272        let regular = vec![json!({"id": 1}), json!({"id": 2})];
1273        assert_eq!(detect_data_structure(&regular), DataStructure::RegularArray);
1274
1275        // グループ化されたデータ
1276        let grouped = vec![
1277            json!([{"cat": "A", "val": 1}, {"cat": "A", "val": 2}]),
1278            json!([{"cat": "B", "val": 3}, {"cat": "B", "val": 4}]),
1279        ];
1280        assert_eq!(detect_data_structure(&grouped), DataStructure::GroupedData);
1281
1282        // プリミティブ値の配列
1283        let primitives = vec![json!(1), json!(2), json!(3)];
1284        assert_eq!(
1285            detect_data_structure(&primitives),
1286            DataStructure::RegularArray
1287        );
1288
1289        // 空配列
1290        let empty: Vec<Value> = vec![];
1291        assert_eq!(detect_data_structure(&empty), DataStructure::RegularArray);
1292    }
1293
1294    #[test]
1295    fn test_apply_sort_with_field_operation() {
1296        let data = vec![
1297            json!({"name": "Alice", "score": 85}),
1298            json!({"name": "Bob", "score": 92}),
1299            json!({"name": "Carol", "score": 78}),
1300        ];
1301
1302        let result = apply_sort_with_field_operation(data, "sort(.score)").unwrap();
1303
1304        // スコア順にソートされているか確認
1305        assert_eq!(result[0].get("score").unwrap(), &json!(78)); // Carol
1306        assert_eq!(result[1].get("score").unwrap(), &json!(85)); // Alice
1307        assert_eq!(result[2].get("score").unwrap(), &json!(92)); // Bob
1308    }
1309
1310    #[test]
1311    fn test_apply_negative_index_slice() {
1312        let data = vec![json!("a"), json!("b"), json!("c"), json!("d"), json!("e")];
1313
1314        // .[-1] - 最後の要素
1315        let result = apply_negative_index_slice(data.clone(), "-1").unwrap();
1316        assert_eq!(result.len(), 1);
1317        assert_eq!(result[0], json!("e"));
1318
1319        // .[-3] - 後ろから3番目
1320        let result = apply_negative_index_slice(data.clone(), "-3").unwrap();
1321        assert_eq!(result.len(), 1);
1322        assert_eq!(result[0], json!("c"));
1323
1324        // 範囲外
1325        let result = apply_negative_index_slice(data.clone(), "-10").unwrap();
1326        assert_eq!(result.len(), 0);
1327    }
1328}