use std::sync::Arc;
use crate::core::{DataType, Error, Result, Row, Value};
use crate::parser::ast::*;
use crate::storage::traits::QueryResult;
use super::context::ExecutionContext;
use super::result::ExecutorMemoryResult;
use super::Executor;
impl Executor {
pub(crate) fn execute_system_schema_table(
&self,
schema_table: &str,
_stmt: &SelectStatement,
_ctx: &ExecutionContext,
) -> Result<Box<dyn QueryResult>> {
match schema_table {
"tables" => self.build_system_tables_result(),
"columns" => self.build_system_columns_result(),
"transactions" => self.build_system_transactions_result(),
_ => Err(Error::TableNotFoundByName(format!(
"system.{}",
schema_table
))),
}
}
fn build_system_tables_result(&self) -> Result<Box<dyn QueryResult>> {
let schemas_guard = self.engine.schemas.read().unwrap();
let columns = vec![
"schema_name".to_string(),
"table_name".to_string(),
"created_at".to_string(),
"updated_at".to_string(),
];
let mut rows: Vec<Row> = Vec::new();
for (schema_name, table_map) in schemas_guard.iter() {
for (table_name, schema) in table_map.iter() {
rows.push(Row::from_values(vec![
Value::Text(Arc::from(schema_name.as_str())),
Value::Text(Arc::from(table_name.as_str())),
Value::Timestamp(schema.created_at),
Value::Timestamp(schema.updated_at),
]));
}
}
Ok(Box::new(ExecutorMemoryResult::new(columns, rows)))
}
fn build_system_columns_result(&self) -> Result<Box<dyn QueryResult>> {
let schemas_guard = self.engine.schemas.read().unwrap();
let columns = vec![
"schema_name".to_string(),
"table_name".to_string(),
"column_name".to_string(),
"ordinal_position".to_string(),
"data_type".to_string(),
"is_nullable".to_string(),
"is_primary_key".to_string(),
"column_default".to_string(),
];
let mut rows: Vec<Row> = Vec::new();
for (schema_name, table_map) in schemas_guard.iter() {
for (table_name, schema) in table_map.iter() {
for (pos, col) in schema.columns.iter().enumerate() {
let ordinal = (pos + 1) as i64;
let data_type = format!("{:?}", col.data_type);
let default_value = col.default_expr.as_ref().and_then(|expr| {
let expr_str = expr.to_string();
let trimmed = expr_str.trim();
if trimmed.is_empty() || trimmed == "NULL" {
None
} else {
Some(trimmed.to_string())
}
});
rows.push(Row::from_values(vec![
Value::Text(Arc::from(schema_name.as_str())),
Value::Text(Arc::from(table_name.as_str())),
Value::Text(Arc::from(col.name.as_str())),
Value::Integer(ordinal),
Value::Text(Arc::from(data_type.as_str())),
Value::Boolean(col.nullable),
Value::Boolean(col.primary_key),
match default_value {
Some(s) => Value::Text(Arc::from(s.as_str())),
None => Value::Null(DataType::Text),
},
]));
}
}
}
Ok(Box::new(ExecutorMemoryResult::new(columns, rows)))
}
fn build_system_transactions_result(&self) -> Result<Box<dyn QueryResult>> {
let registry = self.engine.registry();
let columns = vec![
"id".to_string(),
"state".to_string(),
"started_at".to_string(),
];
let mut rows: Vec<Row> = Vec::new();
let active_count = registry.active_count();
if active_count > 0 {
rows.push(Row::from_values(vec![
Value::Integer(0), Value::Text(Arc::from(format!("ACTIVE ({})", active_count).as_str())),
Value::Null(DataType::Timestamp),
]));
}
Ok(Box::new(ExecutorMemoryResult::new(columns, rows)))
}
}