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    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    /// Get the column reference
36    #[must_use]
37    pub fn column_ref(&self) -> &ColumnRef {
38        &self.column_ref
39    }
40
41    /// Wrap the column output name and its type within the [`ColumnField`]
42    #[must_use]
43    pub fn get_column_field(&self) -> ColumnField {
44        ColumnField::new(self.column_ref.column_id(), *self.column_ref.column_type())
45    }
46
47    /// Get the column identifier
48    #[must_use]
49    pub fn column_id(&self) -> Ident {
50        self.column_ref.column_id()
51    }
52
53    /// Get the column
54    /// # Panics
55    ///
56    /// Will panic if the column is not found. Shouldn't happen in practice since
57    /// code in `sql/parse` should have already checked that the column exists.
58    #[must_use]
59    pub fn fetch_column<'a, S: Scalar>(&self, table: &Table<'a, S>) -> Column<'a, S> {
60        *table
61            .inner_table()
62            .get(&self.column_ref.column_id())
63            .expect("Column not found")
64    }
65}
66
67impl ProofExpr for ColumnExpr {
68    /// Get the data type of the expression
69    fn data_type(&self) -> ColumnType {
70        *self.get_column_reference().column_type()
71    }
72
73    /// Evaluate the column expression and
74    /// add the result to the [`FirstRoundBuilder`](crate::sql::proof::FirstRoundBuilder)
75    fn first_round_evaluate<'a, S: Scalar>(
76        &self,
77        _alloc: &'a Bump,
78        table: &Table<'a, S>,
79        _params: &[LiteralValue],
80    ) -> PlaceholderResult<Column<'a, S>> {
81        Ok(self.fetch_column(table))
82    }
83
84    /// Given the selected rows (as a slice of booleans), evaluate the column expression and
85    /// add the components needed to prove the result
86    fn final_round_evaluate<'a, S: Scalar>(
87        &self,
88        _builder: &mut FinalRoundBuilder<'a, S>,
89        _alloc: &'a Bump,
90        table: &Table<'a, S>,
91        _params: &[LiteralValue],
92    ) -> PlaceholderResult<Column<'a, S>> {
93        Ok(self.fetch_column(table))
94    }
95
96    /// Evaluate the column expression at the sumcheck's random point,
97    /// add components needed to verify this column expression
98    fn verifier_evaluate<S: Scalar>(
99        &self,
100        _builder: &mut impl VerificationBuilder<S>,
101        accessor: &IndexMap<Ident, S>,
102        _chi_eval: S,
103        _params: &[LiteralValue],
104    ) -> Result<S, ProofError> {
105        Ok(*accessor
106            .get(&self.column_ref.column_id())
107            .ok_or(ProofError::VerificationError {
108                error: "Column Not Found",
109            })?)
110    }
111
112    /// Insert in the [`IndexSet`] `columns` all the column
113    /// references in the `BoolExpr` or forwards the call to some
114    /// subsequent `bool_expr`
115    fn get_column_references(&self, columns: &mut IndexSet<ColumnRef>) {
116        columns.insert(self.column_ref.clone());
117    }
118}