diff --git a/querybuilder/atoms/columns.py b/querybuilder/atoms/columns.py index 075a0cd23eac93e2e577ecd4e619f5d5c46b3873..458681209973afa88fc2b871fd3c7dddec3db022 100644 --- a/querybuilder/atoms/columns.py +++ b/querybuilder/atoms/columns.py @@ -493,10 +493,15 @@ class Named(Column): check: Column | Callable[[Named], Column] | None = None, **kwargs, ) -> TableColumn: + if name is None: + name = self.name + if relation_name is None: + relation_name = self.relation_name + assert relation_name is not None return TableColumn( self.sqltype, - name or self.name, - relation_name or self.relation_name, + cast(str, name), + cast(str, relation_name), schema_name=schema_name or self.schema_name, constraints=constraints, check=check, diff --git a/querybuilder/atoms/relations.py b/querybuilder/atoms/relations.py index cab11142c8f17ffd3b4ac26ea1652f657700993e..7d441790afb7dc40e9ba53cbc1c242aeb42181f1 100644 --- a/querybuilder/atoms/relations.py +++ b/querybuilder/atoms/relations.py @@ -223,7 +223,7 @@ class Named(Prenamed, Fromable): additional keyworded parameters (e.g., columns) for super initialization. """ - __slots__: ClassVar[tuple[str, ...]] = () + __slots__ = () _scopable = False _preserve_table_column = False @@ -248,8 +248,15 @@ class Named(Prenamed, Fromable): def from_query(cls: type[Self], query: qb.queries.dql.DQLQuery, name: str) -> Self: return cls(name, columns=query.columns) - def to_table(self, constraints: Iterable[qb.atoms.constraints.TableConstraint] = (), **kwargs) -> Table: - columns = [ qbcolumns.TableColumn(c.sqltype, c.name) for c in self.columns ] + def to_table( + self, constraints: Iterable[qb.atoms.constraints.TableConstraint] = (), **kwargs + ) -> Table: + columns = [ + qbcolumns.TableColumn( + c.sqltype, c.name, self.name, schema_name=self.schema_name + ) + for c in self.columns + ] kwargs |= dict(name=self.name, schema_name=self.schema_name, columns=columns) return Table(**kwargs) @@ -260,7 +267,7 @@ class RecursiveNamed(Named): # Actual classes class Aliased(Named): - __slots__: ClassVar[tuple[str, ...]] = ("subrelation", "column_aliases") + __slots__ = ("subrelation", "column_aliases") def __init__( self, @@ -558,8 +565,14 @@ class Table(Named): column_aliases: Mapping[int, str] | Iterable[tuple[int, str]] = (), constraints: Iterable[qb.atoms.constraints.TableConstraint] = (), **kwargs, - ) -> Self: - aliased = Aliased(subrelation, name=name, schema_name=schema_name, column_aliases=column_aliases, **kwargs) + ) -> Table: + aliased = Aliased( + subrelation, + name=name, + schema_name=schema_name, + column_aliases=column_aliases, + **kwargs, + ) return aliased.to_table(constraints=constraints) def create( @@ -716,7 +729,7 @@ class Table(Named): class View(Named): - __slots__: ClassVar[tuple[str, ...]] = ("defquery", "column_aliases") + __slots__ = ("defquery", "column_aliases") def __init__( self, @@ -730,7 +743,7 @@ class View(Named): self.column_aliases: Mapping[int, str] = Frozenmap(column_aliases) if self.column_aliases: - for i, c in enumerate(self.subrelation.columns): + for i, c in enumerate(self.defquery.columns): if i not in self.column_aliases and not isinstance(c, qbcolumns.Named): raise ValueError("Missing alias for an unnamed column") @@ -739,17 +752,27 @@ class View(Named): def _get_column_names(self): return tuple( self.column_aliases[i] if i in self.column_aliases else c.name - for i, c in enumerate(self.subrelation.columns) + for i, c in enumerate(self.defquery.columns) ) + def _init_columns(self, columns): + assert not columns + @property def columns(self): return self._column_store_factory( ( - qbcolhelpers.name_column(c, self.column_aliases[i]) + qbcolhelpers.name_column( + c, + self.column_aliases[i], + relation_name=self.name, + schema_name=self.schema_name, + ) if i in self.column_aliases - else qbcolhelpers.name_column(c, relation_name=self.name) - for i, c in enumerate(self.subrelation.columns) + else qbcolhelpers.name_column( + c, relation_name=self.name, schema_name=self.schema_name + ) + for i, c in enumerate(self.defquery.columns) ) ) @@ -790,3 +813,11 @@ class View(Named): defquery = self.defquery.substitute(substitutions) return self.buildfrom(self, defquery=defquery) + + def __getstate__(self): + state = super().__getstate__() + state["defquery"] = self.defquery + state["column_aliases"] = self.column_aliases + state["columns"] = None # maybe a little ugly? + + return state