On Tuesday 19 August 2008 09:12:43 Diez B. Roggisch wrote:
> Gaetan de Menten schrieb:
> > On Thu, Aug 14, 2008 at 5:12 PM, Diez B. Roggisch <[EMAIL PROTECTED]> wrote:
> >> I'm mapping an existing schema with elixir. One thing strikes me as odd
> >> is that local_side/remote_side on ManyToMany-relationships can only be
> >> specified (or are respected) when auto-mapping.
> >>
> >> I don't want to auto-map, my desire is to create full mappings so that I
> >> can from then on work with my elixir/sa-model.
> >>
> >> What's the rationale behind not respecting the parameters as
> >> column-names?
> >
> > What exactly do you want to achieve? Do you want to have custom names
> > in your ManyToMany table? If this is the case, isn't the column_format
> > argument enough for you?
>
> I didn't realize it. It might work as well - but certainly it's a bit
> more complicted :)
>
> > And, FWIW, there is no rationale. This is just the way it is because
> > nobody really needed custom names beyond what column_format allows you
> > do to yet. What you suggest is probably a more elegant solution to the
> > column_format argument.
> >
> > I was a bit uneasy to implement it because in the case where several
> > columns are needed on one (or both) side(s), the column names would
> > need to be given in the same order the primary key columns are
> > declared on the targeted entities. Now that I think of it, I don't
> > think it's an unreasonable requirement if it is clearly stated in the
> > documentation. A patch in that direction would be very likely to be
> > accepted ;-).
>
> I will see if I can do that :)

You find the patch attached. I created a test-case, which works flawlessly.

I also introduced a new keyword to ManyToMany - schema. This completes my 
earlier patches as it allows to specify a schema in case of both entities 
being part of different schemas and thus elixir can't decide which one to 
use.

Diez




--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"SQLElixir" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlelixir?hl=en
-~----------~----~----~----~------~----~------~--~---

Index: tests/test_m2m.py
===================================================================
--- tests/test_m2m.py	(revision 396)
+++ tests/test_m2m.py	(working copy)
@@ -9,6 +9,7 @@
 class TestManyToMany(object):
     def setup(self):
         metadata.bind = 'sqlite:///'
+        metadata.bind.echo = True
 
     def teardown(self):
         cleanup_all(True)
@@ -169,3 +170,26 @@
         assert b1 in a2.bs
         assert not a3.bs
 
+    def test_local_and_remote_sidess(self):
+        class A(Entity):
+            key1 = Field(Integer, primary_key=True, autoincrement=False)
+            key2 = Field(String(40), primary_key=True)
+
+            bs_ = ManyToMany('B', local_side=['foo', 'bar'], remote_side="baz")
+
+        class B(Entity):
+            name = Field(String(60))
+            as_ = ManyToMany('A', remote_side=['foo', 'bar'], local_side="baz")
+
+        setup_all(True)
+
+        b1 = B(name='b1', as_=[A(key1=10, key2='a1')])
+
+        session.commit()
+        session.clear()
+
+        a = A.query.one()
+        b = B.query.one()
+
+        assert a in b.as_
+        assert b in a.bs_
Index: elixir/relationships.py
===================================================================
--- elixir/relationships.py	(revision 396)
+++ elixir/relationships.py	(working copy)
@@ -233,17 +233,20 @@
 |                    | and when the table is autoloaded/reflected from the    |
 |                    | database.                                              |
 +--------------------+--------------------------------------------------------+
+| ``schema``         | Specify a custom schema for the intermediate table.    |
+|                    | This can be used both when the tables needs to         |
+|                    | be created and when the table is autoloaded/reflected  |
+|                    | from the database.                                     |
++--------------------+--------------------------------------------------------+
 | ``remote_side``    | A column name or list of column names specifying       |
 |                    | which column(s) in the intermediary table are used     |
 |                    | for the "remote" part of a self-referential            |
-|                    | relationship. This argument has an effect only when    |
-|                    | your entities are autoloaded.                          |
+|                    | relationship.                                          |
 +--------------------+--------------------------------------------------------+
 | ``local_side``     | A column name or list of column names specifying       |
 |                    | which column(s) in the intermediary table are used     |
 |                    | for the "local" part of a self-referential             |
-|                    | relationship. This argument has an effect only when    |
-|                    | your entities are autoloaded.                          |
+|                    | relationship.                                          |
 +--------------------+--------------------------------------------------------+
 | ``order_by``       | Specify which field(s) should be used to sort the      |
 |                    | results given by accessing the relation field. You can |
@@ -748,6 +751,8 @@
         self.column_format = kwargs.pop('column_format', options.M2MCOL_NAMEFORMAT)
 
         self.secondary_table = kwargs.pop('table', None)
+        self.schema = kwargs.pop('schema', None)
+
         self.primaryjoin_clauses = list()
         self.secondaryjoin_clauses = list()
 
@@ -775,8 +780,13 @@
 
         e1_schema = e1_desc.table_options.get('schema', None)
         e2_schema = e2_desc.table_options.get('schema', None)
+
+        if self.schema is not None:
+            e1_schema = e2_schema = self.schema
+
         assert e1_schema == e2_schema, \
-               "Schema %r for entity %s differs from schema %r of entity %s" \
+               "Schema %r for entity %s differs from schema %r of entity %s." \
+               " Consider using the schema-parameter. "\
                % (e1_schema, self.entity.__name__,
                   e2_schema, self.target.__name__)
 
@@ -827,13 +837,19 @@
             constraints = list()
 
             joins = (self.primaryjoin_clauses, self.secondaryjoin_clauses)
+            all_alternative_names = self.local_side, self.remote_side
+
             for num, desc, fk_name, rel in (
                     (0, e1_desc, source_fk_name, self),
                     (1, e2_desc, target_fk_name, self.inverse)):
                 fk_colnames = list()
                 fk_refcols = list()
 
-                for pk_col in desc.primary_keys:
+                alternative_names = all_alternative_names[num]
+                if isinstance(alternative_names, basestring):
+                    alternative_names = [alternative_names]
+
+                for colnum, pk_col in enumerate(desc.primary_keys):
                     colname = self.column_format % \
                               {'tablename': desc.tablename,
                                'key': pk_col.key,
@@ -845,6 +861,9 @@
                     if self.entity is self.target:
                         colname += str(num + 1)
 
+                    if alternative_names:
+                        colname = alternative_names[colnum]
+
                     col = Column(colname, pk_col.type, primary_key=True)
                     columns.append(col)
 

Reply via email to