use schema_core::{ColumnName, Field, FieldName, Filter, Relation, RelationKey, TableName};
pub(super) fn relation_target(relation: &Relation) -> (&TableName, RelationKey<'_>) {
(relation.table(), relation.key())
}
pub(super) fn collect_filter_columns<'a>(
fields: &'a [Field],
out: &mut Vec<(&'a TableName, &'a ColumnName)>,
) {
for field in fields {
if let Some(relation) = field.relation() {
for filter in relation.filters().unwrap_or_default() {
if let Filter::ValueOp(value_op) = filter {
out.push((relation.table(), &value_op.column));
}
}
}
collect_filter_columns(field.children(), out);
}
}
pub(super) fn find_paths<'a>(
fields: &'a [Field],
table: &TableName,
prefix: &mut Vec<&'a Relation>,
out: &mut Vec<Vec<&'a Relation>>,
) {
for field in fields {
match field.relation() {
Some(relation) => {
prefix.push(relation);
let (target, key) = relation_target(relation);
let hit = target == table
|| matches!(key, RelationKey::Through(through) if through.table == *table);
if hit {
out.push(prefix.clone());
}
find_paths(field.children(), table, prefix, out);
prefix.pop();
}
None => find_paths(field.children(), table, prefix, out),
}
}
}
pub(super) fn collect_relation_tables(fields: &[Field], out: &mut Vec<TableName>) {
for field in fields {
if let Some(relation) = field.relation() {
out.push(relation.table().clone());
}
collect_relation_tables(field.children(), out);
}
}
pub(super) fn field_column<'a>(fields: &'a [Field], name: &FieldName) -> Option<&'a ColumnName> {
for field in fields {
if &field.field == name {
return field.column();
}
if let Some(column) = field_column(field.children(), name) {
return Some(column);
}
}
None
}