column copying methods pass foreign key/sequence objects incorrectly

Issue #9 resolved
Mike Bayer repo owner created an issue

initial comment from rtl:

I noticed that SQLAlchemy wasn't generating foreign key references in postgres fully so I spent some time chasing down why.

The scenario is that because my app needs to access a lot of databases (historical data with the same structure in many different physical databases) I've set all the tables to use the ansi sql engine by default and I have a factory that takes the actual postgres engine (determined at run time) and calls toengine() for each table. One of the things that toengine() does is to replicate the Table structure using the specified engine. As part of this replication any specified ForeignKey() constructs are also copied (see schema.py, copy() on line 173 in rev644).

The issue was that the copied foreign key was supplied to the new Column constructor (line 179 in the same file) as a keyword argument - 'foreign_key = fk'. However, this resulted in the copied ForeignKey never having its _set_parent() called because the code in the Column._set_parent() includes the following line:

self._init_items(*self.args)

where self.args are the non-keyword args passed in to the Column constructor and since the copied ForeignKey was passed in as a keyword, its _set_parent() was never called.

One solution is to change line 173 of schema.py to pass the copied ForeignKey as a standard (non-keyword) parameter (see the svn diff below). This works for Postgres at least, resulting in the correct sql statements being issued (and all the existing test passing).

The question is then - is this the best way to fix the problem and if so, should the same fix be applied to the Column._make_proxy() function as well (I don't have enough SQLAlchemy background to say for sure).

Hope there's enough detail in the explanation for people to easily understand the problem :-/

Robert

svn diff....

===================================================================
--- schema.py   (revision 644)
+++ schema.py   (working copy)
@@ -176,7 +176,7 @@
             fk = None
         else:
             fk = self.foreign_key.copy()
-        return Column(self.name, self.type, key = self.key, primary_key = self.primary_key, foreign_key = fk, sequence = self.sequence)
+        return Column(self.name, self.type, fk, key = self.key, primary_key = self.primary_key, sequence = self.sequence)

     def _make_proxy(self, selectable, name = None):
         """creates a copy of this Column, initialized the way this Column is"""

Comments (5)

  1. Mike Bayer reporter

    your fix is exactly correct. however, I also want to nail down the constructors in Table() and Column() to not allow this error. since i need to use **kwargs in order to achieve my particular strange calling style, I added an assertion to the constructors. this actually revealed several more errors in this same area. heres the changeset

  2. Log in to comment