Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion spanner_orm/condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,19 @@ def bind(self, model):

@property
def conditions(self):
"""Generate the child conditions based on the relationship constraints."""
if not self.relation:
raise error.SpannerError(
'Condition must be bound before conditions is called')
return self.relation.conditions + self._conditions
relation_conditions = []
for constraint in self.relation.constraints:
# This is backward from what you might imagine because the condition will
# be processed from the context of the destination model
relation_conditions.append(
ColumnsEqualCondition(constraint.destination_column,
constraint.origin_class,
constraint.origin_column))
return relation_conditions + self._conditions

@property
def destination(self):
Expand Down
32 changes: 20 additions & 12 deletions spanner_orm/relationship.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@

from __future__ import annotations

from typing import Dict, List, Type, Union
from typing import Any, Dict, List, Type, Union

from spanner_orm import condition
import dataclasses
from spanner_orm import error
from spanner_orm import model


@dataclasses.dataclass

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intradasting

class RelationshipConstraint:
destination_class: Type[Any]
destination_column: str
origin_class: Type[Any]
origin_column: str


class Relationship(object):
"""Helps define a foreign key relationship between two models."""

Expand Down Expand Up @@ -52,8 +60,8 @@ def __init__(self,
self.origin = None

@property
def conditions(self) -> List[condition.Condition]:
assert self.origin, 'Origin must be set before conditions is called'
def constraints(self) -> List[RelationshipConstraint]:
assert self.origin, 'Origin must be set before constraints is called'
return self._parse_constraints()

@property
Expand All @@ -66,9 +74,9 @@ def destination(self) -> Type[model.Model]:
def single(self) -> bool:
return self._single

def _parse_constraints(self) -> List[condition.Condition]:
def _parse_constraints(self) -> List[RelationshipConstraint]:
"""Validates the dictionary of constraints and turns it into Conditions."""
conditions = []
constraints = []
for origin_column, destination_column in self._constraints.items():
if origin_column not in self.origin.schema:
raise error.SpannerError(
Expand All @@ -77,10 +85,10 @@ def _parse_constraints(self) -> List[condition.Condition]:
if destination_column not in self.destination.schema:
raise error.SpannerError(
'Destination column must be present in destination model')
# This is backward from what you might imagine because the condition will
# be processed from the context of the destination model
conditions.append(
condition.ColumnsEqualCondition(destination_column, self.origin,
origin_column))

return conditions
# TODO(dbrandao): remove when pytype #234 is fixed
constraints.append(
RelationshipConstraint(self.destination, destination_column,
self.origin, origin_column)) # type: ignore

return constraints