use scythe_core::analyzer::{AnalyzedQuery, CompositeInfo, EnumInfo};
use scythe_core::errors::{ErrorCode, ScytheError};
use crate::GeneratedCode;
#[derive(Debug, Clone)]
pub struct RbsGenerationContext {
pub queries: Vec<RbsQueryInfo>,
pub enums: Vec<RbsEnumInfo>,
}
#[derive(Debug, Clone)]
pub struct RbsQueryInfo {
pub func_name: String,
pub struct_name: Option<String>,
pub columns: Vec<ResolvedColumn>,
pub params: Vec<ResolvedParam>,
pub command: scythe_core::parser::QueryCommand,
}
#[derive(Debug, Clone)]
pub struct RbsEnumInfo {
pub type_name: String,
pub values: Vec<String>,
}
#[derive(Debug, Clone, Default)]
pub struct ResolvedColumn {
pub name: String,
pub field_name: String,
pub lang_type: String,
pub full_type: String,
pub neutral_type: String,
pub nullable: bool,
pub join_group: Option<String>,
pub nullable_before_join: bool,
pub sql_type: String,
}
impl ResolvedColumn {
pub fn is_join_discriminant(&self) -> bool {
self.join_group.is_some() && !self.nullable_before_join
}
}
#[derive(Debug, Clone)]
pub struct ResolvedParam {
pub name: String,
pub field_name: String,
pub lang_type: String,
pub full_type: String,
pub borrowed_type: String,
pub neutral_type: String,
pub nullable: bool,
}
pub struct GroupedQueryFn<'a> {
pub analyzed: &'a AnalyzedQuery,
pub parent_struct_name: &'a str,
pub child_struct_name: &'a str,
pub all_columns: &'a [ResolvedColumn],
pub parent_columns: &'a [ResolvedColumn],
pub child_columns: &'a [ResolvedColumn],
pub params: &'a [ResolvedParam],
pub key_column: &'a str,
}
pub trait CodegenBackend: Send + Sync {
fn name(&self) -> &str;
fn manifest(&self) -> &scythe_backend::manifest::BackendManifest;
fn generate_row_struct(&self, query_name: &str, columns: &[ResolvedColumn]) -> Result<String, ScytheError>;
fn generate_model_struct(&self, table_name: &str, columns: &[ResolvedColumn]) -> Result<String, ScytheError>;
fn generate_query_fn(
&self,
analyzed: &AnalyzedQuery,
struct_name: &str,
columns: &[ResolvedColumn],
params: &[ResolvedParam],
) -> Result<String, ScytheError>;
fn generate_enum_def(&self, enum_info: &EnumInfo) -> Result<String, ScytheError>;
fn generate_composite_def(&self, composite: &CompositeInfo) -> Result<String, ScytheError>;
fn file_header(&self) -> String {
String::new()
}
fn file_header_for_results(&self, _generated: &[GeneratedCode]) -> String {
self.file_header()
}
fn file_footer(&self) -> String {
String::new()
}
fn query_class_header(&self) -> String {
String::new()
}
fn post_footer(&self) -> String {
String::new()
}
fn generate_rbs_file(&self, _context: &RbsGenerationContext) -> Option<String> {
None
}
fn generate_grouped_structs(
&self,
_parent_struct_name: &str,
_child_struct_name: &str,
_parent_columns: &[ResolvedColumn],
_child_columns: &[ResolvedColumn],
_key_column: &str,
) -> Result<String, ScytheError> {
Err(ScytheError::new(
ErrorCode::InternalError,
format!("grouped queries are not yet supported by the '{}' backend", self.name()),
))
}
fn generate_grouped_query_fn(&self, _request: &GroupedQueryFn<'_>) -> Result<String, ScytheError> {
Err(ScytheError::new(
ErrorCode::InternalError,
format!("grouped queries are not yet supported by the '{}' backend", self.name()),
))
}
fn apply_options(&mut self, _options: &std::collections::HashMap<String, String>) -> Result<(), ScytheError> {
Ok(())
}
fn supported_engines(&self) -> &[&str] {
&["postgresql"]
}
}