Skip to main content

hawdb_executor/
output.rs

1// Copyright 2026 Nowledge
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Query result envelope shared by execution and embedded adapters.
16
17use crate::{QueryRows, QuerySchema, QueryValueRows, Row};
18
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct QueryOutput {
21    pub rows: QueryRows,
22}
23
24impl QueryOutput {
25    pub fn from_rows(rows: Vec<Row>) -> Self {
26        Self { rows: rows.into() }
27    }
28
29    pub fn schema(&self) -> &QuerySchema {
30        self.rows.schema()
31    }
32
33    pub fn value_rows(&self) -> QueryValueRows<'_> {
34        self.rows.value_rows()
35    }
36
37    /// Returns the deterministic payload accounting used by query result
38    /// admission. Container allocation overhead is intentionally excluded.
39    pub fn payload_bytes(&self) -> usize {
40        self.rows.payload_bytes()
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47    use crate::QueryRowsBuilder;
48    use hawdb_core::{Value, ValueRef};
49
50    #[test]
51    fn query_output_preserves_schema_values_and_payload_without_map_materialization() {
52        let schema = QuerySchema::try_new(["payload".to_string(), "id".to_string()]).unwrap();
53        let mut rows = QueryRowsBuilder::with_schema(schema.clone(), 1);
54        rows.push_values([Value::String("bytes".to_string()), Value::Int(7)])
55            .unwrap();
56        let output = QueryOutput {
57            rows: rows.finish(),
58        };
59        assert_eq!(output.schema(), &schema);
60        assert_eq!(output.rows.value(0, 0), Some(ValueRef::String("bytes")));
61        assert_eq!(output.value_rows().count(), 1);
62        assert_eq!(output.payload_bytes(), "payload".len() + "id".len() + 5 + 8);
63        assert_eq!(output.clone(), output);
64        let empty = QueryOutput::from_rows(Vec::new());
65        assert!(empty.schema().is_empty());
66        assert_eq!(empty.payload_bytes(), 0);
67    }
68}