#[derive(Debug, Clone)]
pub struct RelationConfig {
pub field_name: String,
pub target_table: String,
pub local_key: String,
pub foreign_key: String,
pub target_columns: Vec<String>,
pub is_many: bool,
pub nested: Vec<RelationConfig>,
}
impl RelationConfig {
fn new(
field_name: &str,
target_table: &str,
local_key: &str,
foreign_key: &str,
target_columns: &[&str],
is_many: bool,
) -> Self {
Self {
field_name: field_name.to_owned(),
target_table: target_table.to_owned(),
local_key: local_key.to_owned(),
foreign_key: foreign_key.to_owned(),
target_columns: target_columns.iter().map(|c| (*c).to_owned()).collect(),
is_many,
nested: Vec::new(),
}
}
}
pub struct RelationalSelectBuilder {
pub(super) source_table: String,
pub(super) source_columns: Vec<String>,
pub(super) relations: Vec<RelationConfig>,
}
impl RelationalSelectBuilder {
pub fn new(source_table: &str, columns: &[&str]) -> Self {
Self {
source_table: source_table.to_owned(),
source_columns: columns.iter().map(|c| (*c).to_owned()).collect(),
relations: Vec::new(),
}
}
pub fn with_many(
mut self,
field_name: &str,
target_table: &str,
local_key: &str,
foreign_key: &str,
target_columns: &[&str],
) -> Self {
self.relations.push(RelationConfig::new(
field_name,
target_table,
local_key,
foreign_key,
target_columns,
true,
));
self
}
pub fn with_one(
mut self,
field_name: &str,
target_table: &str,
local_key: &str,
foreign_key: &str,
target_columns: &[&str],
) -> Self {
self.relations.push(RelationConfig::new(
field_name,
target_table,
local_key,
foreign_key,
target_columns,
false,
));
self
}
pub fn relation_configs(&self) -> &[RelationConfig] {
&self.relations
}
pub fn source_table(&self) -> &str {
&self.source_table
}
pub fn source_columns(&self) -> &[String] {
&self.source_columns
}
pub(super) fn push_source_select(&self, sql: &mut String) {
for (i, col) in self.source_columns.iter().enumerate() {
if i > 0 {
sql.push_str(", ");
}
push_qualified(sql, &self.source_table, col);
}
}
pub(super) fn push_column_list(sql: &mut String, qualifier: &str, columns: &[String]) {
for (i, col) in columns.iter().enumerate() {
if i > 0 {
sql.push_str(", ");
}
push_qualified(sql, qualifier, col);
}
}
pub(super) fn push_join_where(
&self,
sql: &mut String,
target_qualifier: &str,
rel: &RelationConfig,
) {
sql.push_str(" WHERE ");
push_qualified(sql, target_qualifier, &rel.foreign_key);
sql.push_str(" = ");
push_qualified(sql, &self.source_table, &rel.local_key);
if !rel.is_many {
sql.push_str(" LIMIT 1");
}
}
}
fn push_qualified(sql: &mut String, qualifier: &str, column: &str) {
sql.push('"');
sql.push_str(qualifier);
sql.push_str("\".\"");
sql.push_str(column);
sql.push('"');
}