Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Ticket #701 (closed defect: fixed)

Opened 12 years ago

Last modified 8 years ago

[PATCH][TEST] catwalk.Browse.join_foreign_key makes bad SQLObject column name from joinColumn

Reported by: nedwards@… Owned by:
Priority: low Milestone: 2.0.* bugfix
Component: Toolbox.Catwalk Version: 1.0.4b1
Severity: major Keywords:

Description (last modified by Chris Arndt) (diff)

Just after upgrade from 0.9a1 to 0.9a2...

In catwalk.Browse.join_foreign_key (turbogears/toolbox/catwalk/browse.py:190), a SQLObject.SORelatedJoin column is passed in, and join_foreign_key needs to determine the SQLObject column name of the foreign key in the SQLObject that this column refers to. However, the SORelatedJoin column only has the database version of the foreign key column name, and attempts to reconstruct the SQLObject name of the column as follows:

   foreign_key = "%sID"%column.joinColumn.split('_')[0]

which is bad in many ways, but in particular, suppose the SQL column name is a ForeignKey? multiWordIdentifier, then the database column name is multi_word_identifier_id, but this hack generates "multiID" and an exception ensues.

Current (very bad) patch is to ask the other table for all of its columns to see which one matches the .joinColumn string and use its name.

foreign_key = [ cl.name for cl in column.otherClass.sqlmeta.columnList if cl.dbName == column.joinColumn ][0]

Very ugly. However, I don't see any other facility for reverse mapping dbName to name.



class PeptideMapping(SQLObject):
  codingSequence = ForeignKey('CodingSequence')

class CodingSequence(SQLObject):
  peptideMapping = RelatedJoin('PeptideMapping')


31/Mar/2006:11:03:37 HTTP INFO Page handler: <bound method Browse.index of <turbogears.toolbox.catwalk.browse.Browse object at 0xb6cb1e0c>>
Traceback (most recent call last):
  File "/fs/hpcbioprojects/python/lib/python2.4/site-packages/CherryPy-2.2.0rc1-py2.4.egg/cherrypy/_cphttptools.py", line 99, in _run
  File "/fs/hpcbioprojects/python/lib/python2.4/site-packages/CherryPy-2.2.0rc1-py2.4.egg/cherrypy/_cphttptools.py", line 248, in main
    body = page_handler(*virtual_path, **self.params)
  File "<string>", line 3, in index
  File "/fs/hpcbioprojects/python/lib/python2.4/site-packages/TurboGears-0.9a2-py2.4.egg/turbogears/controllers.py", line 207, in expose
    output = database.run_with_transaction(expose._expose,func, accept, allow_json, allow_json_from_config,*args, **kw)
  File "/fs/hpcbioprojects/python/lib/python2.4/site-packages/TurboGears-0.9a2-py2.4.egg/turbogears/database.py", line 216, in run_with_transaction
    retval = func(*args, **kw)
  File "<string>", line 5, in _expose
  File "/fs/hpcbioprojects/python/lib/python2.4/site-packages/TurboGears-0.9a2-py2.4.egg/turbogears/controllers.py", line 228, in <lambda>
    expose._expose.when(rule)(lambda _func, accept, allow_json, allow_json_from_config,*args,**kw: _execute_func(
  File "/fs/hpcbioprojects/python/lib/python2.4/site-packages/TurboGears-0.9a2-py2.4.egg/turbogears/controllers.py", line 246, in _execute_func
    output = errorhandling.try_call(func, *args, **kw)
  File "/fs/hpcbioprojects/python/lib/python2.4/site-packages/TurboGears-0.9a2-py2.4.egg/turbogears/errorhandling.py", line 59, in try_call
    output = func(self, *args, **kw)
  File "/fs/hpcbiohomes/nedwards/projects/python/lib/python2.4/site-packages/TurboGears-0.9a2-py2.4.egg/turbogears/toolbox/catwalk/browse.py", line 20, in index
    total,rows = self.rows_for_model(object_name,start,page_size,filters)
  File "/fs/hpcbiohomes/nedwards/projects/python/lib/python2.4/site-packages/TurboGears-0.9a2-py2.4.egg/turbogears/toolbox/catwalk/browse.py", line 119, in rows_for_model
    relations = self.relation_values(object_name,rows)
  File "/fs/hpcbiohomes/nedwards/projects/python/lib/python2.4/site-packages/TurboGears-0.9a2-py2.4.egg/turbogears/toolbox/catwalk/browse.py", line 138, in relation_values
  File "/fs/hpcbiohomes/nedwards/projects/python/lib/python2.4/site-packages/TurboGears-0.9a2-py2.4.egg/turbogears/toolbox/catwalk/browse.py", line 195, in join_foreign_key
    return getattr(column.otherClass.q,foreign_key)
  File "/fs/hpcbioprojects/python/lib/python2.4/site-packages/SQLObject-0.7.1dev_r1457-py2.4.egg/sqlobject/sqlbuilder.py", line 362, in __getattr__
KeyError: 'codingID'
Request Headers:
  COOKIE: tg-visit=1e956a910599a39aac022a574d7591f2b7e20cf5
  ACCEPT-CHARSET: ISO-8859-1,utf-8;q=0.7,*;q=0.7
  USER-AGENT: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20060111 Firefox/
  CONNECTION: keep-alive
  HOST: codon.umiacs.umd.edu:8888
  ACCEPT: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
  ACCEPT-LANGUAGE: en-us,en;q=0.5
  ACCEPT-ENCODING: gzip,deflate
  KEEP-ALIVE: 300 - - [31/Mar/2006:11:03:37] "GET /catwalk/browse/?object_name=CodingSequence HTTP/1.1" 500 3535


test_catwalk_701.py Download (1.7 KB) - added by JoostM 11 years ago.
701.diff Download (576 bytes) - added by JoostM 11 years ago.
patch against the trunk

Change History

comment:1 Changed 12 years ago by anonymous

  • Version set to 0.9a4

comment:2 Changed 11 years ago by jorge.vargas

  • Milestone set to 1.1

does this still happens?

comment:3 Changed 11 years ago by jorge.vargas

  • Component changed from Toolbox to Toolbox.Catwalk

comment:4 Changed 11 years ago by hads

Yes, this still occurs.

comment:5 Changed 11 years ago by hads

The solution above does not seem to work for me.

comment:6 Changed 11 years ago by Joost

The catwalk code could be improved by using the same syntax as used in sqlobject.joins:

foreign_key = column.soClass.sqlmeta.style.dbColumnToPythonAttr(column.joinColumn)

However, SQLObject is self seems to be broken when it comes to naming. E.g:

>>> from sqlobject import *
>>> from turbogears.database import AutoConnectHub
>>> hub = AutoConnectHub()
>>> __connection__ = hub
>>> class Pet(SQLObject):
...     class sqlmeta:
...         table = 'tg_pet'
...     name = StringCol()
...     user = ForeignKey("User")
>>> class User(SQLObject):
...     class sqlmeta:
...         table = "tg_user"
...     name = StringCol()
...     my_pet = SingleJoin("Pet")
>>> from turbogears import database
>>> database.set_db_uri("sqlite:///:memory:")
>>> User.createTable(ifNotExists=True)
>>> Pet.createTable(ifNotExists=True)
>>> u = User(name="jhon")
>>> u.my_pet
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<string>", line 1, in <lambda>
  File "c:\python24\lib\site-packages\SQLObject-0.7.2-py2.4.egg\sqlobject\joins.py", line 293, in performJoin
    results = self.otherClass.select(
  File "c:\python24\lib\site-packages\SQLObject-0.7.2-py2.4.egg\sqlobject\sqlbuilder.py", line 374, in __getattr__
    raise AttributeError("%s instance has no attribute '%s'" % (self.soClass.__name__, attr))
AttributeError: Pet instance has no attribute 'tgUserID'

Changed 11 years ago by JoostM


Changed 11 years ago by JoostM

patch against the trunk

comment:8 Changed 11 years ago by JoostM

  • Summary changed from catwalk.Browse.join_foreign_key makes bad SQLObject column name from joinColumn to [PATCH][TEST] catwalk.Browse.join_foreign_key makes bad SQLObject column name from joinColumn

comment:9 Changed 11 years ago by jorge.vargas

  • Owner changed from anonymous to jorge.vargas

i'll try to take a look at this and commit it if possible.

comment:10 Changed 11 years ago by harrybozack

I attempted the proposed solution by Joost and I still get similar errors.

comment:11 Changed 11 years ago by alberto

  • Milestone changed from 1.1 to __unclassified__

Batch moved into unclassified from 1.1 to properly track progress on the later

comment:11 Changed 10 years ago by Kylotan

  • Version changed from 0.9a4 to 1.0.4b1

I just posted on bug 1412, but this is perhaps more relevant to my case. CamelCase foreign key names seem to lose the second word when the join is constructed, and end up looking for an ID that doesn't exist. eg. A join between MotorCar? and MotorCarDefinition? ends up failing because it can't find MotorID in the second object, when it should be looking for MotorCarID instead.

comment:12 Changed 9 years ago by jorge.vargas

  • Owner jorge.vargas deleted

comment:13 Changed 9 years ago by jorge.vargas

  • Description modified (diff)
  • Milestone changed from __unclassified__ to 1.x

comment:14 Changed 8 years ago by Chris Arndt

  • Status changed from new to closed
  • Priority changed from high to low
  • Resolution set to fixed
  • Description modified (diff)

This was fixed long ago in r5101.

comment:15 Changed 8 years ago by Chris Arndt

  • Milestone changed from 1.x to 2.* bugfix
Note: See TracTickets for help on using tickets.