proof_of_sql/sql/proof_exprs/
column_expr.rs

1use super::ProofExpr;
2use crate::{
3    base::{
4        database::{Column, ColumnField, ColumnRef, ColumnType, LiteralValue, Table},
5        map::{IndexMap, IndexSet},
6        proof::{PlaceholderResult, 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 first_round_evaluate<'a, S: Scalar>(
70        &self,
71        _alloc: &'a Bump,
72        table: &Table<'a, S>,
73        _params: &[LiteralValue],
74    ) -> PlaceholderResult<Column<'a, S>> {
75        Ok(self.fetch_column(table))
76    }
77
78    /// Given the selected rows (as a slice of booleans), evaluate the column expression and
79    /// add the components needed to prove the result
80    fn final_round_evaluate<'a, S: Scalar>(
81        &self,
82        _builder: &mut FinalRoundBuilder<'a, S>,
83        _alloc: &'a Bump,
84        table: &Table<'a, S>,
85        _params: &[LiteralValue],
86    ) -> PlaceholderResult<Column<'a, S>> {
87        Ok(self.fetch_column(table))
88    }
89
90    /// Evaluate the column expression at the sumcheck's random point,
91    /// add components needed to verify this column expression
92    fn verifier_evaluate<S: Scalar>(
93        &self,
94        _builder: &mut impl VerificationBuilder<S>,
95        accessor: &IndexMap<ColumnRef, S>,
96        _chi_eval: S,
97        _params: &[LiteralValue],
98    ) -> Result<S, ProofError> {
99        Ok(*accessor
100            .get(&self.column_ref)
101            .ok_or(ProofError::VerificationError {
102                error: "Column Not Found",
103            })?)
104    }
105
106    /// Insert in the [`IndexSet`] `columns` all the column
107    /// references in the `BoolExpr` or forwards the call to some
108    /// subsequent `bool_expr`
109    fn get_column_references(&self, columns: &mut IndexSet<ColumnRef>) {
110        columns.insert(self.column_ref.clone());
111    }
112}