mod aggregate;
mod lowered;
mod route;
mod write;
use crate::{
db::{
DbSession, PersistedRow, QueryError,
executor::EntityAuthority,
query::{intent::StructuralQuery, plan::AccessPlannedQuery},
session::sql::{
CompiledSqlCommand, SqlCompiledCommandCacheKey, SqlStatementResult,
projection::{SqlProjectionPayload, execute_sql_projection_rows_for_canister},
},
},
traits::{CanisterKind, EntityValue},
};
impl<C: CanisterKind> DbSession<C> {
fn prepare_structural_sql_projection_execution(
&self,
query: StructuralQuery,
authority: EntityAuthority,
compiled_cache_key: Option<&SqlCompiledCommandCacheKey>,
) -> Result<(Vec<String>, AccessPlannedQuery), QueryError> {
let entry =
self.planned_sql_select_with_visibility(&query, authority, compiled_cache_key)?;
let (plan, columns) = entry.into_parts();
Ok((columns, plan))
}
pub(in crate::db::session::sql) fn execute_structural_sql_projection(
&self,
query: StructuralQuery,
authority: EntityAuthority,
compiled_cache_key: Option<&SqlCompiledCommandCacheKey>,
) -> Result<SqlProjectionPayload, QueryError> {
let (columns, plan) =
self.prepare_structural_sql_projection_execution(query, authority, compiled_cache_key)?;
let projected =
execute_sql_projection_rows_for_canister(&self.db, self.debug, authority, plan)
.map_err(QueryError::execute)?;
let (rows, row_count) = projected.into_parts();
Ok(SqlProjectionPayload::new(columns, rows, row_count))
}
pub(in crate::db) fn execute_compiled_sql<E>(
&self,
compiled: &CompiledSqlCommand,
) -> Result<SqlStatementResult, QueryError>
where
E: PersistedRow<Canister = C> + EntityValue,
{
let authority = EntityAuthority::for_type::<E>();
match compiled {
CompiledSqlCommand::Select {
query,
compiled_cache_key,
} => {
if query.has_grouping() {
return self.execute_structural_sql_grouped_statement_select_core(
query.clone(),
authority,
compiled_cache_key.as_ref(),
);
}
let payload = self.execute_structural_sql_projection(
query.clone(),
authority,
compiled_cache_key.as_ref(),
)?;
Ok(payload.into_statement_result())
}
CompiledSqlCommand::Delete { query, statement } => {
self.execute_sql_delete_statement::<E>(query.clone(), statement)
}
CompiledSqlCommand::GlobalAggregate {
command,
label_override,
} => self.execute_global_aggregate_statement_for_authority(
command.clone(),
authority,
label_override.clone(),
),
CompiledSqlCommand::Explain(lowered) => {
if let Some(explain) =
self.explain_lowered_sql_execution_for_authority(lowered, authority)?
{
return Ok(SqlStatementResult::Explain(explain));
}
self.explain_lowered_sql_for_authority(lowered, authority)
.map(SqlStatementResult::Explain)
}
CompiledSqlCommand::Insert(statement) => {
self.execute_sql_insert_statement::<E>(statement)
}
CompiledSqlCommand::Update(statement) => {
self.execute_sql_update_statement::<E>(statement)
}
CompiledSqlCommand::DescribeEntity => {
Ok(SqlStatementResult::Describe(self.describe_entity::<E>()))
}
CompiledSqlCommand::ShowIndexesEntity => {
Ok(SqlStatementResult::ShowIndexes(self.show_indexes::<E>()))
}
CompiledSqlCommand::ShowColumnsEntity => {
Ok(SqlStatementResult::ShowColumns(self.show_columns::<E>()))
}
CompiledSqlCommand::ShowEntities => {
Ok(SqlStatementResult::ShowEntities(self.show_entities()))
}
}
}
#[cfg(test)]
pub(in crate::db) fn execute_sql_statement_inner<E>(
&self,
sql_statement: &crate::db::sql::parser::SqlStatement,
) -> Result<SqlStatementResult, QueryError>
where
E: PersistedRow<Canister = C> + EntityValue,
{
let compiled = Self::compile_sql_statement_inner::<E>(sql_statement)?;
self.execute_compiled_sql::<E>(&compiled)
}
}