From 513d374ede75030d82a64e0548b6b54f9dc8dcc5 Mon Sep 17 00:00:00 2001 From: Ian Joiner <14581281+iajoiner@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:09:49 -0500 Subject: [PATCH] refactor!: let `ProofPlan::result_evaluate` and `final_round_evaluate` return `Table` --- .../proof-of-sql/src/sql/proof/proof_plan.rs | 6 +- .../proof-of-sql/src/sql/proof/query_proof.rs | 13 ++-- .../src/sql/proof/query_proof_test.rs | 60 +++++++++++++------ .../sql/proof/verifiable_query_result_test.rs | 16 +++-- .../src/sql/proof_plans/dyn_proof_plan.rs | 2 +- .../src/sql/proof_plans/empty_exec.rs | 10 ++-- .../src/sql/proof_plans/filter_exec.rs | 20 +++++-- .../src/sql/proof_plans/filter_exec_test.rs | 44 +++++++++----- .../filter_exec_test_dishonest_prover.rs | 20 +++++-- .../src/sql/proof_plans/group_by_exec.rs | 36 +++++++---- .../src/sql/proof_plans/projection_exec.rs | 36 +++++++---- .../sql/proof_plans/projection_exec_test.rs | 32 ++++++---- .../src/sql/proof_plans/table_exec.rs | 23 +++---- 13 files changed, 215 insertions(+), 103 deletions(-) diff --git a/crates/proof-of-sql/src/sql/proof/proof_plan.rs b/crates/proof-of-sql/src/sql/proof/proof_plan.rs index e2b01b0c0..edfe1f371 100644 --- a/crates/proof-of-sql/src/sql/proof/proof_plan.rs +++ b/crates/proof-of-sql/src/sql/proof/proof_plan.rs @@ -1,6 +1,6 @@ use super::{CountBuilder, FinalRoundBuilder, FirstRoundBuilder, VerificationBuilder}; use crate::base::{ - database::{Column, ColumnField, ColumnRef, DataAccessor, OwnedTable, TableRef}, + database::{ColumnField, ColumnRef, DataAccessor, OwnedTable, Table, TableRef}, map::{IndexMap, IndexSet}, proof::ProofError, scalar::Scalar, @@ -40,7 +40,7 @@ pub trait ProverEvaluate { &self, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec>; + ) -> Table<'a, S>; /// Evaluate the query and modify `FirstRoundBuilder` to form the query's proof. fn first_round_evaluate(&self, builder: &mut FirstRoundBuilder); @@ -56,7 +56,7 @@ pub trait ProverEvaluate { builder: &mut FinalRoundBuilder<'a, S>, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec>; + ) -> Table<'a, S>; } /// Marker used as a trait bound for generic [`ProofPlan`] types to indicate the honesty of their implementation. diff --git a/crates/proof-of-sql/src/sql/proof/query_proof.rs b/crates/proof-of-sql/src/sql/proof/query_proof.rs index b10e53393..9fba7b5bc 100644 --- a/crates/proof-of-sql/src/sql/proof/query_proof.rs +++ b/crates/proof-of-sql/src/sql/proof/query_proof.rs @@ -6,7 +6,7 @@ use crate::{ base::{ bit::BitDistribution, commitment::CommitmentEvaluationProof, - database::{Column, CommitmentAccessor, DataAccessor, MetadataAccessor, TableRef}, + database::{CommitmentAccessor, DataAccessor, MetadataAccessor, TableRef}, map::IndexMap, math::log2_up, polynomial::{compute_evaluation_vector, CompositePolynomialInfo}, @@ -76,9 +76,14 @@ impl QueryProof { let alloc = Bump::new(); // Evaluate query result - let result_cols = expr.result_evaluate(&alloc, accessor); - let output_length = result_cols.first().map_or(0, Column::len); - let provable_result = ProvableQueryResult::new(output_length as u64, &result_cols); + let result_table = expr.result_evaluate(&alloc, accessor); + let result_cols = result_table + .inner_table() + .values() + .cloned() + .collect::>(); + let provable_result = + ProvableQueryResult::new(result_table.num_rows() as u64, &result_cols); // Prover First Round let mut first_round_builder = FirstRoundBuilder::new(); diff --git a/crates/proof-of-sql/src/sql/proof/query_proof_test.rs b/crates/proof-of-sql/src/sql/proof/query_proof_test.rs index 1e1a82a4f..3f231b831 100644 --- a/crates/proof-of-sql/src/sql/proof/query_proof_test.rs +++ b/crates/proof-of-sql/src/sql/proof/query_proof_test.rs @@ -7,9 +7,9 @@ use crate::{ database::{ owned_table_utility::{bigint, owned_table}, Column, ColumnField, ColumnRef, ColumnType, DataAccessor, OwnedTable, - OwnedTableTestAccessor, TableRef, + OwnedTableTestAccessor, Table, TableRef, }, - map::{indexset, IndexMap, IndexSet}, + map::{indexmap, indexset, IndexMap, IndexSet}, proof::ProofError, scalar::{Curve25519Scalar, Scalar}, }, @@ -44,9 +44,12 @@ impl ProverEvaluate for TrivialTestProofPlan { &self, alloc: &'a Bump, _accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let col = alloc.alloc_slice_fill_copy(self.length, self.column_fill_value); - vec![Column::BigInt(col)] + Table::<'a, S>::try_new(indexmap! { + "a1".parse().unwrap() => Column::BigInt(col), + }) + .unwrap() } fn first_round_evaluate(&self, _builder: &mut FirstRoundBuilder) {} @@ -56,14 +59,17 @@ impl ProverEvaluate for TrivialTestProofPlan { builder: &mut FinalRoundBuilder<'a, S>, alloc: &'a Bump, _accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let col = alloc.alloc_slice_fill_copy(self.length, self.column_fill_value); builder.produce_intermediate_mle(col as &[_]); builder.produce_sumcheck_subpolynomial( SumcheckSubpolynomialType::Identity, vec![(S::ONE, vec![Box::new(col as &[_])])], ); - vec![Column::BigInt(col)] + Table::<'a, S>::try_new(indexmap! { + "a1".parse().unwrap() => Column::BigInt(col), + }) + .unwrap() } } impl ProofPlan for TrivialTestProofPlan { @@ -213,9 +219,12 @@ impl ProverEvaluate for SquareTestProofPlan { &self, alloc: &'a Bump, _accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let res: &[_] = alloc.alloc_slice_copy(&self.res); - vec![Column::BigInt(res)] + Table::<'a, S>::try_new(indexmap! { + "a1".parse().unwrap() => Column::BigInt(res), + }) + .unwrap() } fn first_round_evaluate(&self, _builder: &mut FirstRoundBuilder) {} @@ -225,7 +234,7 @@ impl ProverEvaluate for SquareTestProofPlan { builder: &mut FinalRoundBuilder<'a, S>, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let x = accessor.get_column(ColumnRef::new( "sxt.test".parse().unwrap(), "x".parse().unwrap(), @@ -240,7 +249,10 @@ impl ProverEvaluate for SquareTestProofPlan { (-S::ONE, vec![Box::new(x), Box::new(x)]), ], ); - vec![Column::BigInt(res)] + Table::<'a, S>::try_new(indexmap! { + "a1".parse().unwrap() => Column::BigInt(&[9, 25]), + }) + .unwrap() } } impl ProofPlan for SquareTestProofPlan { @@ -390,9 +402,12 @@ impl ProverEvaluate for DoubleSquareTestProofPlan { &self, alloc: &'a Bump, _accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let res: &[_] = alloc.alloc_slice_copy(&self.res); - vec![Column::BigInt(res)] + Table::<'a, S>::try_new(indexmap! { + "a1".parse().unwrap() => Column::BigInt(res), + }) + .unwrap() } fn first_round_evaluate(&self, _builder: &mut FirstRoundBuilder) {} @@ -402,7 +417,7 @@ impl ProverEvaluate for DoubleSquareTestProofPlan { builder: &mut FinalRoundBuilder<'a, S>, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let x = accessor.get_column(ColumnRef::new( "sxt.test".parse().unwrap(), "x".parse().unwrap(), @@ -430,7 +445,10 @@ impl ProverEvaluate for DoubleSquareTestProofPlan { ], ); builder.produce_intermediate_mle(res); - vec![Column::BigInt(res)] + Table::<'a, S>::try_new(indexmap! { + "a1".parse().unwrap() => Column::BigInt(res), + }) + .unwrap() } } impl ProofPlan for DoubleSquareTestProofPlan { @@ -597,8 +615,11 @@ impl ProverEvaluate for ChallengeTestProofPlan { &self, _alloc: &'a Bump, _accessor: &'a dyn DataAccessor, - ) -> Vec> { - vec![Column::BigInt(&[9, 25])] + ) -> Table<'a, S> { + Table::<'a, S>::try_new(indexmap! { + "a1".parse().unwrap() => Column::BigInt(&[9, 25]), + }) + .unwrap() } fn first_round_evaluate(&self, builder: &mut FirstRoundBuilder) { @@ -610,7 +631,7 @@ impl ProverEvaluate for ChallengeTestProofPlan { builder: &mut FinalRoundBuilder<'a, S>, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let x = accessor.get_column(ColumnRef::new( "sxt.test".parse().unwrap(), "x".parse().unwrap(), @@ -627,7 +648,10 @@ impl ProverEvaluate for ChallengeTestProofPlan { (-alpha, vec![Box::new(x), Box::new(x)]), ], ); - vec![Column::BigInt(&[9, 25])] + Table::<'a, S>::try_new(indexmap! { + "a1".parse().unwrap() => Column::BigInt(&[9, 25]), + }) + .unwrap() } } impl ProofPlan for ChallengeTestProofPlan { diff --git a/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test.rs b/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test.rs index 7417fc2ef..12a594129 100644 --- a/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test.rs +++ b/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test.rs @@ -8,7 +8,7 @@ use crate::{ database::{ owned_table_utility::{bigint, owned_table}, Column, ColumnField, ColumnRef, ColumnType, DataAccessor, OwnedTable, - OwnedTableTestAccessor, TableRef, + OwnedTableTestAccessor, Table, TableRef, }, map::{indexset, IndexMap, IndexSet}, proof::ProofError, @@ -29,10 +29,13 @@ impl ProverEvaluate for EmptyTestQueryExpr { &self, alloc: &'a Bump, _accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let zeros = vec![0; self.length]; let res: &[_] = alloc.alloc_slice_copy(&zeros); - vec![Column::BigInt(res); self.columns] + Table::<'a, S>::try_from_iter( + (1..=self.columns).map(|i| (format!("a{i}").parse().unwrap(), Column::BigInt(res))), + ) + .unwrap() } fn first_round_evaluate(&self, _builder: &mut FirstRoundBuilder) {} fn final_round_evaluate<'a, S: Scalar>( @@ -40,13 +43,16 @@ impl ProverEvaluate for EmptyTestQueryExpr { builder: &mut FinalRoundBuilder<'a, S>, alloc: &'a Bump, _accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let zeros = vec![0; self.length]; let res: &[_] = alloc.alloc_slice_copy(&zeros); let _ = std::iter::repeat_with(|| builder.produce_intermediate_mle(res)) .take(self.columns) .collect::>(); - vec![Column::BigInt(res); self.columns] + Table::<'a, S>::try_from_iter( + (1..=self.columns).map(|i| (format!("a{i}").parse().unwrap(), Column::BigInt(res))), + ) + .unwrap() } } impl ProofPlan for EmptyTestQueryExpr { diff --git a/crates/proof-of-sql/src/sql/proof_plans/dyn_proof_plan.rs b/crates/proof-of-sql/src/sql/proof_plans/dyn_proof_plan.rs index 2a09f0529..11acca0ea 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/dyn_proof_plan.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/dyn_proof_plan.rs @@ -1,7 +1,7 @@ use super::{EmptyExec, FilterExec, GroupByExec, ProjectionExec, TableExec}; use crate::{ base::{ - database::{Column, ColumnField, ColumnRef, DataAccessor, OwnedTable, TableRef}, + database::{ColumnField, ColumnRef, DataAccessor, OwnedTable, Table, TableRef}, map::{IndexMap, IndexSet}, proof::ProofError, scalar::Scalar, diff --git a/crates/proof-of-sql/src/sql/proof_plans/empty_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/empty_exec.rs index 0ee0d92fc..b6673cab7 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/empty_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/empty_exec.rs @@ -1,6 +1,6 @@ use crate::{ base::{ - database::{Column, ColumnField, ColumnRef, DataAccessor, OwnedTable, TableRef}, + database::{ColumnField, ColumnRef, DataAccessor, OwnedTable, Table, TableRef}, map::{IndexMap, IndexSet}, proof::ProofError, scalar::Scalar, @@ -67,8 +67,8 @@ impl ProverEvaluate for EmptyExec { &self, _alloc: &'a Bump, _accessor: &'a dyn DataAccessor, - ) -> Vec> { - Vec::new() + ) -> Table<'a, S> { + Table::<'a, S>::try_new(IndexMap::default()).unwrap() } fn first_round_evaluate(&self, _builder: &mut FirstRoundBuilder) {} @@ -80,7 +80,7 @@ impl ProverEvaluate for EmptyExec { _builder: &mut FinalRoundBuilder<'a, S>, _alloc: &'a Bump, _accessor: &'a dyn DataAccessor, - ) -> Vec> { - Vec::new() + ) -> Table<'a, S> { + Table::<'a, S>::try_new(IndexMap::default()).unwrap() } } diff --git a/crates/proof-of-sql/src/sql/proof_plans/filter_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/filter_exec.rs index b8380c87f..884613e41 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/filter_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/filter_exec.rs @@ -141,7 +141,7 @@ impl ProverEvaluate for FilterExec { &self, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let column_refs = self.get_column_references(); let used_table = accessor.get_table(self.table.table_ref, &column_refs); // 1. selection @@ -159,7 +159,13 @@ impl ProverEvaluate for FilterExec { // Compute filtered_columns and indexes let (filtered_columns, _) = filter_columns(alloc, &columns, selection); - filtered_columns + Table::<'a, S>::try_from_iter( + self.aliased_results + .iter() + .map(|expr| expr.alias) + .zip(filtered_columns), + ) + .expect("Failed to create table from iterator") } fn first_round_evaluate(&self, builder: &mut FirstRoundBuilder) { @@ -173,7 +179,7 @@ impl ProverEvaluate for FilterExec { builder: &mut FinalRoundBuilder<'a, S>, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let column_refs = self.get_column_references(); let used_table = accessor.get_table(self.table.table_ref, &column_refs); // 1. selection @@ -214,7 +220,13 @@ impl ProverEvaluate for FilterExec { &filtered_columns, result_len, ); - filtered_columns + Table::<'a, S>::try_from_iter( + self.aliased_results + .iter() + .map(|expr| expr.alias) + .zip(filtered_columns), + ) + .expect("Failed to create table from iterator") } } diff --git a/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test.rs b/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test.rs index ca52a65c3..1e8ee53b5 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test.rs @@ -2,8 +2,8 @@ use super::{test_utility::*, FilterExec}; use crate::{ base::{ database::{ - owned_table_utility::*, Column, ColumnField, ColumnRef, ColumnType, LiteralValue, - OwnedTable, OwnedTableTestAccessor, TableRef, TestAccessor, + owned_table_utility::*, ColumnField, ColumnRef, ColumnType, LiteralValue, OwnedTable, + OwnedTableTestAccessor, TableRef, TestAccessor, }, map::{IndexMap, IndexSet}, math::decimal::Precision, @@ -194,8 +194,12 @@ fn we_can_get_an_empty_result_from_a_basic_filter_on_an_empty_table_using_result where_clause, ); let alloc = Bump::new(); - let result_cols = expr.result_evaluate(&alloc, &accessor); - let output_length = result_cols.first().map_or(0, Column::len) as u64; + let result_table = expr.result_evaluate(&alloc, &accessor); + let result_cols = result_table + .inner_table() + .values() + .cloned() + .collect::>(); let mut builder = FirstRoundBuilder::new(); expr.first_round_evaluate(&mut builder); let fields = &[ @@ -208,7 +212,7 @@ fn we_can_get_an_empty_result_from_a_basic_filter_on_an_empty_table_using_result ), ]; let res: OwnedTable = - ProvableQueryResult::new(output_length as u64, &result_cols) + ProvableQueryResult::new(result_table.num_rows() as u64, &result_cols) .to_owned_table(fields) .unwrap(); let expected: OwnedTable = owned_table([ @@ -240,8 +244,12 @@ fn we_can_get_an_empty_result_from_a_basic_filter_using_result_evaluate() { where_clause, ); let alloc = Bump::new(); - let result_cols = expr.result_evaluate(&alloc, &accessor); - let output_length = result_cols.first().map_or(0, Column::len) as u64; + let result_table = expr.result_evaluate(&alloc, &accessor); + let result_cols = result_table + .inner_table() + .values() + .cloned() + .collect::>(); let mut builder = FirstRoundBuilder::new(); expr.first_round_evaluate(&mut builder); let fields = &[ @@ -254,7 +262,7 @@ fn we_can_get_an_empty_result_from_a_basic_filter_using_result_evaluate() { ), ]; let res: OwnedTable = - ProvableQueryResult::new(output_length as u64, &result_cols) + ProvableQueryResult::new(result_table.num_rows() as u64, &result_cols) .to_owned_table(fields) .unwrap(); let expected: OwnedTable = owned_table([ @@ -282,13 +290,17 @@ fn we_can_get_no_columns_from_a_basic_filter_with_no_selected_columns_using_resu let where_clause: DynProofExpr = equal(column(t, "a", &accessor), const_int128(5)); let expr = filter(cols_expr_plan(t, &[], &accessor), tab(t), where_clause); let alloc = Bump::new(); - let result_cols = expr.result_evaluate(&alloc, &accessor); - let output_length = result_cols.first().map_or(0, Column::len) as u64; + let result_table = expr.result_evaluate(&alloc, &accessor); + let result_cols = result_table + .inner_table() + .values() + .cloned() + .collect::>(); let mut builder = FirstRoundBuilder::new(); expr.first_round_evaluate(&mut builder); let fields = &[]; let res: OwnedTable = - ProvableQueryResult::new(output_length as u64, &result_cols) + ProvableQueryResult::new(result_table.num_rows() as u64, &result_cols) .to_owned_table(fields) .unwrap(); let expected = OwnedTable::try_new(IndexMap::default()).unwrap(); @@ -314,8 +326,12 @@ fn we_can_get_the_correct_result_from_a_basic_filter_using_result_evaluate() { where_clause, ); let alloc = Bump::new(); - let result_cols = expr.result_evaluate(&alloc, &accessor); - let output_length = result_cols.first().map_or(0, Column::len) as u64; + let result_table = expr.result_evaluate(&alloc, &accessor); + let result_cols = result_table + .inner_table() + .values() + .cloned() + .collect::>(); let mut builder = FirstRoundBuilder::new(); expr.first_round_evaluate(&mut builder); let fields = &[ @@ -328,7 +344,7 @@ fn we_can_get_the_correct_result_from_a_basic_filter_using_result_evaluate() { ), ]; let res: OwnedTable = - ProvableQueryResult::new(output_length as u64, &result_cols) + ProvableQueryResult::new(result_table.num_rows() as u64, &result_cols) .to_owned_table(fields) .unwrap(); let expected: OwnedTable = owned_table([ diff --git a/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test_dishonest_prover.rs b/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test_dishonest_prover.rs index 07f18b4bf..176eb6fd5 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test_dishonest_prover.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test_dishonest_prover.rs @@ -37,7 +37,7 @@ impl ProverEvaluate for DishonestFilterExec { &self, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let column_refs = self.get_column_references(); let used_table = accessor.get_table(self.table.table_ref, &column_refs); // 1. selection @@ -54,7 +54,13 @@ impl ProverEvaluate for DishonestFilterExec { // Compute filtered_columns let (filtered_columns, _) = filter_columns(alloc, &columns, selection); let filtered_columns = tamper_column(alloc, filtered_columns); - filtered_columns + Table::<'a, S>::try_from_iter( + self.aliased_results + .iter() + .map(|expr| expr.alias) + .zip(filtered_columns), + ) + .expect("Failed to create table from iterator") } fn first_round_evaluate(&self, builder: &mut FirstRoundBuilder) { @@ -72,7 +78,7 @@ impl ProverEvaluate for DishonestFilterExec { builder: &mut FinalRoundBuilder<'a, S>, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let column_refs = self.get_column_references(); let used_table = accessor.get_table(self.table.table_ref, &column_refs); // 1. selection @@ -113,7 +119,13 @@ impl ProverEvaluate for DishonestFilterExec { &filtered_columns, result_len, ); - filtered_columns + Table::<'a, S>::try_from_iter( + self.aliased_results + .iter() + .map(|expr| expr.alias) + .zip(filtered_columns), + ) + .expect("Failed to create table from iterator") } } diff --git a/crates/proof-of-sql/src/sql/proof_plans/group_by_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/group_by_exec.rs index 0773da752..b5251fada 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/group_by_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/group_by_exec.rs @@ -200,7 +200,7 @@ impl ProverEvaluate for GroupByExec { &self, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let column_refs = self.get_column_references(); let used_table = accessor.get_table(self.table.table_ref, &column_refs); // 1. selection @@ -230,11 +230,18 @@ impl ProverEvaluate for GroupByExec { } = aggregate_columns(alloc, &group_by_columns, &sum_columns, &[], &[], selection) .expect("columns should be aggregatable"); let sum_result_columns_iter = sum_result_columns.iter().map(|col| Column::Scalar(col)); - group_by_result_columns - .into_iter() - .chain(sum_result_columns_iter) - .chain(iter::once(Column::BigInt(count_column))) - .collect::>() + Table::<'a, S>::try_from_iter( + self.get_column_result_fields() + .into_iter() + .map(|field| field.name()) + .zip( + group_by_result_columns + .into_iter() + .chain(sum_result_columns_iter) + .chain(iter::once(Column::BigInt(count_column))), + ), + ) + .expect("Failed to create table from column references") } fn first_round_evaluate(&self, builder: &mut FirstRoundBuilder) { @@ -248,7 +255,7 @@ impl ProverEvaluate for GroupByExec { builder: &mut FinalRoundBuilder<'a, S>, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let column_refs = self.get_column_references(); let used_table = accessor.get_table(self.table.table_ref, &column_refs); // 1. selection @@ -288,16 +295,23 @@ impl ProverEvaluate for GroupByExec { // 4. Tally results let sum_result_columns_iter = sum_result_columns.iter().map(|col| Column::Scalar(col)); - let res = group_by_result_columns + let columns = group_by_result_columns .clone() .into_iter() .chain(sum_result_columns_iter) - .chain(core::iter::once(Column::BigInt(count_column))) + .chain(iter::once(Column::BigInt(count_column))) .collect::>(); + let res = Table::<'a, S>::try_from_iter( + self.get_column_result_fields() + .into_iter() + .map(|field| field.name()) + .zip(columns.clone().into_iter()), + ) + .expect("Failed to create table from column references"); // 5. Produce MLEs - res.iter().copied().for_each(|column| { + for column in columns.into_iter() { builder.produce_intermediate_mle(column); - }); + } // 6. Prove group by prove_group_by( builder, diff --git a/crates/proof-of-sql/src/sql/proof_plans/projection_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/projection_exec.rs index 6c90b2a47..bbb96a86b 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/projection_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/projection_exec.rs @@ -1,6 +1,6 @@ use crate::{ base::{ - database::{Column, ColumnField, ColumnRef, DataAccessor, OwnedTable, TableRef}, + database::{ColumnField, ColumnRef, DataAccessor, OwnedTable, Table, TableRef}, map::{IndexMap, IndexSet}, proof::ProofError, scalar::Scalar, @@ -89,8 +89,9 @@ impl ProverEvaluate for ProjectionExec { &self, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let column_refs = self.get_column_references(); +<<<<<<< HEAD let used_table = accessor.get_table(self.table.table_ref, &column_refs); let columns: Vec<_> = self .aliased_results @@ -98,6 +99,17 @@ impl ProverEvaluate for ProjectionExec { .map(|aliased_expr| aliased_expr.expr.result_evaluate(alloc, &used_table)) .collect(); columns +======= + let used_table = + Table::<'a, S>::from_columns(&column_refs, self.table.table_ref, accessor, alloc); + Table::<'a, S>::try_from_iter(self.aliased_results.iter().map(|aliased_expr| { + ( + aliased_expr.alias, + aliased_expr.expr.result_evaluate(alloc, &used_table), + ) + })) + .expect("Failed to create table from iterator") +>>>>>>> 531ba7cc (refactor!: let `ProofPlan::result_evaluate` and `final_round_evaluate` return `Table`) } fn first_round_evaluate(&self, _builder: &mut FirstRoundBuilder) {} @@ -113,21 +125,19 @@ impl ProverEvaluate for ProjectionExec { builder: &mut FinalRoundBuilder<'a, S>, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let column_refs = self.get_column_references(); let used_table = accessor.get_table(self.table.table_ref, &column_refs); // 1. Evaluate result expressions - let res: Vec<_> = self - .aliased_results - .iter() - .map(|aliased_expr| { - aliased_expr - .expr - .prover_evaluate(builder, alloc, &used_table) - }) - .collect(); + let res = Table::<'a, S>::try_from_iter(self.aliased_results.iter().map(|aliased_expr| { + ( + aliased_expr.alias, + aliased_expr.expr.result_evaluate(alloc, &used_table), + ) + })) + .expect("Failed to create table from iterator"); // 2. Produce MLEs - res.clone().into_iter().for_each(|column| { + res.inner_table().values().for_each(|column| { builder.produce_intermediate_mle(column.as_scalar(alloc)); }); res diff --git a/crates/proof-of-sql/src/sql/proof_plans/projection_exec_test.rs b/crates/proof-of-sql/src/sql/proof_plans/projection_exec_test.rs index dede8b063..372d22ec8 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/projection_exec_test.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/projection_exec_test.rs @@ -2,7 +2,7 @@ use super::{test_utility::*, DynProofPlan, ProjectionExec}; use crate::{ base::{ database::{ - owned_table_utility::*, Column, ColumnField, ColumnRef, ColumnType, OwnedTable, + owned_table_utility::*, ColumnField, ColumnRef, ColumnType, OwnedTable, OwnedTableTestAccessor, TableRef, TestAccessor, }, map::{IndexMap, IndexSet}, @@ -168,8 +168,12 @@ fn we_can_get_an_empty_result_from_a_basic_projection_on_an_empty_table_using_re let expr: DynProofPlan = projection(cols_expr_plan(t, &["b", "c", "d", "e"], &accessor), tab(t)); let alloc = Bump::new(); - let result_cols = expr.result_evaluate(&alloc, &accessor); - let output_length = result_cols.first().map_or(0, Column::len) as u64; + let result_table = expr.result_evaluate(&alloc, &accessor); + let result_cols = result_table + .inner_table() + .values() + .cloned() + .collect::>(); let mut builder = FirstRoundBuilder::new(); expr.first_round_evaluate(&mut builder); let fields = &[ @@ -182,7 +186,7 @@ fn we_can_get_an_empty_result_from_a_basic_projection_on_an_empty_table_using_re ), ]; let res: OwnedTable = - ProvableQueryResult::new(output_length as u64, &result_cols) + ProvableQueryResult::new(result_table.num_rows() as u64, &result_cols) .to_owned_table(fields) .unwrap(); let expected: OwnedTable = owned_table([ @@ -209,13 +213,17 @@ fn we_can_get_no_columns_from_a_basic_projection_with_no_selected_columns_using_ accessor.add_table(t, data, 0); let expr: DynProofPlan = projection(cols_expr_plan(t, &[], &accessor), tab(t)); let alloc = Bump::new(); - let result_cols = expr.result_evaluate(&alloc, &accessor); - let output_length = result_cols.first().map_or(0, Column::len) as u64; + let result_table = expr.result_evaluate(&alloc, &accessor); + let result_cols = result_table + .inner_table() + .values() + .cloned() + .collect::>(); let mut builder = FirstRoundBuilder::new(); expr.first_round_evaluate(&mut builder); let fields = &[]; let res: OwnedTable = - ProvableQueryResult::new(output_length as u64, &result_cols) + ProvableQueryResult::new(result_table.num_rows() as u64, &result_cols) .to_owned_table(fields) .unwrap(); let expected = OwnedTable::try_new(IndexMap::default()).unwrap(); @@ -247,8 +255,12 @@ fn we_can_get_the_correct_result_from_a_basic_projection_using_result_evaluate() tab(t), ); let alloc = Bump::new(); - let result_cols = expr.result_evaluate(&alloc, &accessor); - let output_length = result_cols.first().map_or(0, Column::len) as u64; + let result_table = expr.result_evaluate(&alloc, &accessor); + let result_cols = result_table + .inner_table() + .values() + .cloned() + .collect::>(); let mut builder = FirstRoundBuilder::new(); expr.first_round_evaluate(&mut builder); let fields = &[ @@ -261,7 +273,7 @@ fn we_can_get_the_correct_result_from_a_basic_projection_using_result_evaluate() ), ]; let res: OwnedTable = - ProvableQueryResult::new(output_length as u64, &result_cols) + ProvableQueryResult::new(result_table.num_rows() as u64, &result_cols) .to_owned_table(fields) .unwrap(); let expected: OwnedTable = owned_table([ diff --git a/crates/proof-of-sql/src/sql/proof_plans/table_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/table_exec.rs index 4a61f0cd9..d3346120b 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/table_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/table_exec.rs @@ -1,6 +1,6 @@ use crate::{ base::{ - database::{Column, ColumnField, ColumnRef, DataAccessor, OwnedTable, TableRef}, + database::{ColumnField, ColumnRef, DataAccessor, OwnedTable, Table, TableRef}, map::{indexset, IndexMap, IndexSet}, proof::ProofError, scalar::Scalar, @@ -33,17 +33,18 @@ impl TableExec { } /// Returns the entire table. - fn get_table<'a, S: Scalar>(&self, accessor: &'a dyn DataAccessor) -> Vec> { - self.schema - .iter() - .map(|field| { + fn get_table<'a, S: Scalar>(&self, accessor: &'a dyn DataAccessor) -> Table<'a, S> { + Table::<'a, S>::try_from_iter(self.schema.iter().map(|field| { + ( + field.name(), accessor.get_column(ColumnRef::new( self.table_ref, field.name(), field.data_type(), - )) - }) - .collect() + )), + ) + })) + .expect("Failed to create table from column references") } } @@ -87,7 +88,7 @@ impl ProverEvaluate for TableExec { &self, _alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { self.get_table(accessor) } @@ -100,9 +101,9 @@ impl ProverEvaluate for TableExec { builder: &mut FinalRoundBuilder<'a, S>, alloc: &'a Bump, accessor: &'a dyn DataAccessor, - ) -> Vec> { + ) -> Table<'a, S> { let table = self.get_table(accessor); - for column in &table { + for column in table.inner_table().values() { builder.produce_intermediate_mle(column.as_scalar(alloc)); } table