use crate::{
errors::ExecutorError, evaluator::CombinedExpressionEvaluator, schema::CombinedSchema,
};
pub(crate) fn execute_values(
rows: &[Vec<vibesql_ast::Expression>],
alias: &str,
column_aliases: Option<&Vec<String>>,
database: Option<&vibesql_storage::Database>,
cte_results: Option<&std::collections::HashMap<String, crate::select::cte::CteResult>>,
) -> Result<super::FromResult, ExecutorError> {
if rows.is_empty() {
let num_columns = column_aliases.map(|ca| ca.len()).unwrap_or(0);
let column_names: Vec<String> = column_aliases
.cloned()
.unwrap_or_else(|| (0..num_columns).map(|i| format!("column{}", i + 1)).collect());
let column_types = vec![vibesql_types::DataType::Null; num_columns];
let schema =
CombinedSchema::from_derived_table(alias.to_string(), column_names, column_types);
return Ok(super::FromResult::from_rows(schema, vec![]));
}
let expected_columns = rows[0].len();
let empty_schema = CombinedSchema::empty();
let empty_row = vibesql_storage::Row::new(vec![]);
let mut evaluator = if let Some(db) = database {
CombinedExpressionEvaluator::with_database(&empty_schema, db)
} else {
CombinedExpressionEvaluator::new(&empty_schema)
};
if let Some(ctes) = cte_results {
if !ctes.is_empty() {
evaluator = evaluator.with_cte_context(ctes);
}
}
let mut result_rows = Vec::with_capacity(rows.len());
for (row_idx, row_exprs) in rows.iter().enumerate() {
if row_exprs.len() != expected_columns {
return Err(ExecutorError::ColumnCountMismatch {
expected: expected_columns,
provided: row_exprs.len(),
});
}
let mut values = Vec::with_capacity(row_exprs.len());
for expr in row_exprs {
let value = evaluator.eval(expr, &empty_row).map_err(|e| {
ExecutorError::TypeError(format!(
"Error evaluating VALUES row {}: {}",
row_idx + 1,
e
))
})?;
values.push(value);
}
result_rows.push(vibesql_storage::Row::new(values));
}
let column_names: Vec<String> = if let Some(aliases) = column_aliases {
if aliases.len() != expected_columns {
return Err(ExecutorError::ColumnCountMismatch {
expected: expected_columns,
provided: aliases.len(),
});
}
aliases.clone()
} else {
(0..expected_columns).map(|i| format!("column{}", i + 1)).collect()
};
let column_types: Vec<vibesql_types::DataType> = result_rows
.first()
.map(|row| row.values.iter().map(|v| v.get_type()).collect())
.unwrap_or_else(|| vec![vibesql_types::DataType::Null; expected_columns]);
let schema = CombinedSchema::from_derived_table(alias.to_string(), column_names, column_types);
Ok(super::FromResult::from_rows(schema, result_rows))
}