qualia_core_db/sparql_library/
range_select_apply.rs1use super::sparql_ast::{BindingRow, ExpressionId, SparqlQueryContext, VariableId, MAX_VARIABLES};
4use super::sparql_filter::{EvalResult, ExpressionEvaluator};
5
6#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
7pub struct SelectWrapperState {
8 pub skipped: u64,
9 pub emitted: u64,
10}
11
12#[derive(Clone, Copy, Debug, Eq, PartialEq)]
13pub struct SelectApplyPage {
14 pub returned: usize,
15 pub limit_reached: bool,
16}
17
18pub fn apply_select_wrappers(
19 ctx: &SparqlQueryContext,
20 filters: &[ExpressionId],
21 filter_count: u8,
22 projection: [VariableId; MAX_VARIABLES],
23 projection_count: u8,
24 limit: u64,
25 offset: u64,
26 state: &mut SelectWrapperState,
27 input: &[BindingRow],
28 out: &mut [BindingRow],
29) -> Result<SelectApplyPage, String> {
30 let mut returned = 0usize;
31 for row in input {
32 let mut accepted = true;
33 for filter in filters.iter().take(filter_count as usize) {
34 if !matches!(
35 ExpressionEvaluator::evaluate(*filter, ctx, row),
36 Ok(EvalResult::Boolean(true))
37 ) {
38 accepted = false;
39 break;
40 }
41 }
42 if !accepted {
43 continue;
44 }
45 if state.skipped < offset {
46 state.skipped += 1;
47 continue;
48 }
49 if state.emitted >= limit {
50 return Ok(SelectApplyPage {
51 returned,
52 limit_reached: true,
53 });
54 }
55 let mut projected = *row;
56 if projection_count != 0 {
57 let mut next = BindingRow::default();
58 for variable in projection.iter().take(projection_count as usize) {
59 if let Some(value) = projected.get(*variable) {
60 next.set(*variable, value);
61 }
62 }
63 projected = next;
64 }
65 if returned == out.len() {
66 return Ok(SelectApplyPage {
67 returned,
68 limit_reached: false,
69 });
70 }
71 out[returned] = projected;
72 returned += 1;
73 state.emitted += 1;
74 }
75 Ok(SelectApplyPage {
76 returned,
77 limit_reached: state.emitted >= limit,
78 })
79}