proof_of_sql/sql/proof_exprs/
column_expr.rs

1use super::ProofExpr;
2use crate::{
3    base::{
4        database::{Column, ColumnField, ColumnRef, ColumnType, Table},
5        map::{IndexMap, IndexSet},
6        proof::ProofError,
7        scalar::Scalar,
8    },
9    sql::proof::{FinalRoundBuilder, VerificationBuilder},
10};
11use bumpalo::Bump;
12use serde::{Deserialize, Serialize};
13use sqlparser::ast::Ident;
14/// Provable expression for a column
15///
16/// Note: this is currently limited to named column expressions.
17#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
18pub struct ColumnExpr {
19    pub(crate) column_ref: ColumnRef,
20}
21
22impl ColumnExpr {
23    /// Create a new column expression
24    #[must_use]
25    pub fn new(column_ref: ColumnRef) -> Self {
26        Self { column_ref }
27    }
28
29    /// Return the column referenced by this [`ColumnExpr`]
30    #[must_use]
31    pub fn get_column_reference(&self) -> ColumnRef {
32        self.column_ref.clone()
33    }
34
35    /// Wrap the column output name and its type within the [`ColumnField`]
36    #[must_use]
37    pub fn get_column_field(&self) -> ColumnField {
38        ColumnField::new(self.column_ref.column_id(), *self.column_ref.column_type())
39    }
40
41    /// Get the column identifier
42    #[must_use]
43    pub fn column_id(&self) -> Ident {
44        self.column_ref.column_id()
45    }
46
47    /// Get the column
48    /// # Panics
49    ///
50    /// Will panic if the column is not found. Shouldn't happen in practice since
51    /// code in `sql/parse` should have already checked that the column exists.
52    #[must_use]
53    pub fn fetch_column<'a, S: Scalar>(&self, table: &Table<'a, S>) -> Column<'a, S> {
54        *table
55            .inner_table()
56            .get(&self.column_ref.column_id())
57            .expect("Column not found")
58    }
59}
60
61impl ProofExpr for ColumnExpr {
62    /// Get the data type of the expression
63    fn data_type(&self) -> ColumnType {
64        *self.get_column_reference().column_type()
65    }
66
67    /// Evaluate the column expression and
68    /// add the result to the [`FirstRoundBuilder`](crate::sql::proof::FirstRoundBuilder)
69    fn result_evaluate<'a, S: Scalar>(
70        &self,
71        _alloc: &'a Bump,
72        table: &Table<'a, S>,
73    ) -> Column<'a, S> {
74        self.fetch_column(table)
75    }
76
77    /// Given the selected rows (as a slice of booleans), evaluate the column expression and
78    /// add the components needed to prove the result
79    fn prover_evaluate<'a, S: Scalar>(
80        &self,
81        _builder: &mut FinalRoundBuilder<'a, S>,
82        _alloc: &'a Bump,
83        table: &Table<'a, S>,
84    ) -> Column<'a, S> {
85        self.fetch_column(table)
86    }
87
88    /// Evaluate the column expression at the sumcheck's random point,
89    /// add components needed to verify this column expression
90    fn verifier_evaluate<S: Scalar>(
91        &self,
92        _builder: &mut impl VerificationBuilder<S>,
93        accessor: &IndexMap<ColumnRef, S>,
94        _chi_eval: S,
95    ) -> Result<S, ProofError> {
96        Ok(*accessor
97            .get(&self.column_ref)
98            .ok_or(ProofError::VerificationError {
99                error: "Column Not Found",
100            })?)
101    }
102
103    /// Insert in the [`IndexSet`] `columns` all the column
104    /// references in the `BoolExpr` or forwards the call to some
105    /// subsequent `bool_expr`
106    fn get_column_references(&self, columns: &mut IndexSet<ColumnRef>) {
107        columns.insert(self.column_ref.clone());
108    }
109}