Opened 19 years ago
Closed 17 years ago
#3642 closed (wontfix)
[multi-db] Filters with nested foreign keys across databases fail
| Reported by: | Owned by: | nobody | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | other branch |
| Severity: | Keywords: | multi-db | |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
If you have two or more databases:
DATABASE_ENGINE = 'mysql' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
DATABASE_NAME = 'djangodb' # Or path to database file if using sqlite3.
DATABASE_USER = 'root' # Not used with sqlite3.
DATABASE_PASSWORD = # Not used with sqlite3.
DATABASE_HOST = 'somehost' # Set to empty string for localhost. Not used with sqlite3.
DATABASE_PORT = # Set to empty string for default. Not used with sqlite3.
OTHER_DATABASES = {
'mortgagedb': {
'DATABASE_NAME': 'mortgagedb',
'DATABASE_USER': 'root',
'DATABASE_PASSWORD': ,
'MODELS': mortgagedb
},
'userdb': {
'DATABASE_NAME': 'userdb',
'DATABASE_USER': 'root',
'DATABASE_PASSWORD': ,
'MODELS': userdb
},
.
.
.
Then you have models that look like this:
Users Model:
class Company(models.Model):
company_id = models.AutoField(primary_key=True)
company_name = models.CharField(blank=True, maxlength=150)
....other properties
class UserInfo(models.Model):
user_id = models.AutoField(primary_key=True)
login = models.CharField(blank=True, maxlength=765)
first_name = models.CharField(blank=True, maxlength=60)
middle_name = models.CharField(blank=True, maxlength=60)
last_name = models.CharField(blank=True, maxlength=60)
company = models.ForeignKey(Company,related_name="company_users")
Loans Model:
(import users model up top)
class Mortgage(models.Model):
mortgage_id = models.AutoField(primary_key=True)
property = models.ForeignKey(Property)
obligor_user = models.ForeignKey(UserInfo, null=True)
Then in the views if you try to do this:
paramsnew = {}
paramsnewobligor_user__company__company_name= request.POSTcompany_name # istartswith fails too, as well as trying to do company ids with in
mortgages = Mortgage.objects.filter(params).distinct() #Mortgage.objects.filter(params) fails too
You get the following error:
Exception Value: (1146, "Table 'mortgagedb.user_info' doesn't exist")
Exception Location: /usr/lib/python2.4/site-packages/MySQLdb/connections.py in defaulterrorhandler, line 33
Traceback (innermost last)
Switch to copy-and-paste view
- /usr/lib/python2.4/site-packages/Django-0.95-py2.4.egg/django/core/handlers/base.py in get_response
- # Apply view middleware
- for middleware_method in self._view_middleware:
- response = middleware_method(request, callback, callback_args, callback_kwargs)
- if response:
- return response 72.
- try:
- response = callback(request, *callback_args, callback_kwargs) ...
- except Exception, e:
- # If the view raised an exception, run it through exception
- # middleware, and if the exception middleware returns a
- # response, use that. Otherwise, reraise the exception.
- for middleware_method in self._exception_middleware:
- response = middleware_method(request, e)
~': ':~', 'HTTP_~': '', 'PATH_INFO': '/mortgageadmin/', 'PATH_TRANSLATED': None, 'QUERY_STRING': None, 'REMOTE_ADDR': '192.168.1.111', 'REMOTE_HOST': None, 'REMOTE_IDENT': None, 'REMOTE_USER': None, 'REQUEST_METHOD': 'POST', 'SCRIPT_NAME': None, 'SERVER_NAME': 'rssws1d.realdatacenter.com', 'SERVER_PORT': 0, 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'mod_python'}> resolver <django.core.urlresolvers.RegexURLResolver object at 0xb705c7ec> response None self <django.core.handlers.modpython.ModPythonHandler object at 0xb724dfcc> settings <django.conf.LazySettings object at 0xb7202acc> urlresolvers <module 'django.core.urlresolvers' from '/usr/lib/python2.4/site-packages/Django-0.95-py2.4.egg/django/core/urlresolvers.pyc'> - /home/carole/rssproject/rsswww/views/mortgages.py in rendermortgageadmin
- paramsappraiser_user__user_id = current_user.user_id 130.
- # do they need to filter the list further?
- count = 0
- if request.session.get("SortMortgageListBy"):
- count = Mortgage.objects.filter(params).order_by(request.session.get("SortMortgageListBy")).distinct().count()
- else:
- count = Mortgage.objects.filter(params).distinct().count() ... 137.
- if count > 300:
- specialtitle="View A Filtered List Of Mortgages:"
- # we want to have them filter the list down some..this number is too much to look at anyway
- return render_to_response('mortgageadmin.html',{'mortgagecount':count,'displayfilter':"yes",'specialtitle':specialtitle,'current_role':current_role,'company_name':company_name,'city':city,'state':state,'zip':zip,'menu':menu},context_instance=RequestContext(request))
- else:
~': ':~', 'HTTP_~': '', 'PATH_INFO': '/mortgageadmin/', 'PATH_TRANSLATED': None, 'QUERY_STRING': None, 'REMOTE_ADDR': '192.168.1.111', 'REMOTE_HOST': None, 'REMOTE_IDENT': None, 'REMOTE_USER': None, 'REQUEST_METHOD': 'POST', 'SCRIPT_NAME': None, 'SERVER_NAME': 'rssws1d.realdatacenter.com', 'SERVER_PORT': 0, 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'mod_python'}> sort specialtitle 'Your Current Mortgages' state zip - /usr/lib/python2.4/site-packages/Django-0.95-py2.4.egg/django/db/models/query.py in count
- counter._limit = None
- counter._select_related = False
- select, sql, params = counter._get_sql_clause()
- cursor = connection.cursor()
- if self._distinct:
- id_col = "%s.%s" % (backend.quote_name(self.model._meta.db_table),
- backend.quote_name(self.model._meta.pk.column))
- cursor.execute("SELECT COUNT(DISTINCT(%s))" % id_col + sql, params) ...
- else:
- cursor.execute("SELECT COUNT(*)" + sql, params)
- return cursor.fetchone()[0] 206.
- def get(self, *args, kwargs):
- "Performs the SELECT and returns a single object matching the given keyword arguments."
mortgage.mortgage_id' params ['Trinity', 50001L] select ['mortgage.mortgage_id', 'mortgage.property_id', 'mortgage.user_id', 'mortgage.credit_score', 'mortgage.ltarv', 'mortgage.ltv_current', 'mortgage.ltv_after', 'mortgage.mortgage_amount', 'mortgage.estimated_months', 'mortgage.obligor_user_id', 'mortgage.obligor_company_id', 'mortgage.receiver_company_id', 'mortgage.closing_agent_user_id', 'mortgage.closing_agent_company_id', 'mortgage.mortgage_broker_user_id', 'mortgage.mortgage_broker_company_id', 'mortgage.title_company_id', 'mortgage.title_company_user_id', 'mortgage.assignment_date', 'mortgage.letter_date', 'mortgage.origination_date', 'mortgage.cancellation_date', 'mortgage.fail_to_close_date', 'mortgage.mature_date', 'mortgage.payoff_date', 'mortgage.completion_date', 'mortgage.life_of_loan', 'mortgage.originator_user_id', 'mortgage.originator_company_id', 'mortgage.escrow', 'mortgage.loan_amount', 'mortgage.payoff_amount', 'mortgage.appraisal', 'mortgage.loan_to_value', 'mortgage.points', 'mortgage.points_dollars', 'mortgage.interest_rate', 'mortgage.interest_amount', 'mortgage.cost_of_credit_yearly_rate', 'mortgage.finance_charge', 'mortgage.number_of_payments', 'mortgage.total_payments', 'mortgage.daily_interest', 'mortgage.days_of_interest', 'mortgage.deferred_interest', 'mortgage.total_interest', 'mortgage.due_date', 'mortgage.first_payment_month_year', 'mortgage.last_payment_month_year', 'mortgage.update_user_id', 'mortgage.address_id', 'mortgage.time_stamp'] self Error in formatting:(1146, "Table 'mortgagedb.user_info' doesn't exist") sql ' FROMmortgageINNER JOINuser_infoASmortgage__obligor_userONmortgage.obligor_user_id=mortgage__obligor_user.user_idINNER JOINcompanyASmortgage__obligor_user__companyONmortgage__obligor_user.company_id=mortgage__obligor_user__company.company_idWHERE (mortgage__obligor_user__company.company_name= %s ANDmortgage.originator_user_id= %s)' - /usr/lib/python2.4/site-packages/Django-0.95-py2.4.egg/django/db/backends/util.py in execute
- def init(self, cursor, db):
- self.cursor = cursor
- self.db = db 8.
- def execute(self, sql, params=()):
- start = time()
- try:
- return self.cursor.execute(sql, params) ...
- finally:
- stop = time()
- # If params was a list, convert it to a tuple, because string
- # formatting with '%' only works with tuples or dicts.
- if not isinstance(params, (tuple, dict)):
- params = tuple(params)
▶ Local vars
Variable Value
params
('Trinity', 50001L)
self
<django.db.backends.util.CursorDebugWrapper object at 0xb6c85cac>
sql
'SELECT COUNT(DISTINCT(mortgage.mortgage_id)) FROMmortgageINNER JOINuser_infoASmortgage__obligor_userONmortgage.obligor_user_id=mortgage__obligor_user.user_idINNER JOINcompanyASmortgage__obligor_user__companyONmortgage__obligor_user.company_id=mortgage__obligor_user__company.company_idWHERE (mortgage__obligor_user__company.company_name= %s ANDmortgage.originator_user_id= %s)'
start
1172897283.3177619
stop
1172897283.3196101
- /usr/lib/python2.4/site-packages/Django-0.95-py2.4.egg/django/db/backends/mysql/base.py in execute
- # It's only used when DEBUG=True.
- class MysqlDebugWrapper:
- def init(self, cursor):
- self.cursor = cursor 32.
- def execute(self, sql, params=()):
- try:
- return self.cursor.execute(sql, params) ...
- except Database.Warning, w:
- self.cursor.execute("SHOW WARNINGS")
- raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall()) 39.
- def executemany(self, sql, param_list):
- try:
mortgage.mortgage_id)) FROMmortgageINNER JOINuser_infoASmortgage__obligor_userONmortgage.obligor_user_id=mortgage__obligor_user.user_idINNER JOINcompanyASmortgage__obligor_user__companyONmortgage__obligor_user.company_id=mortgage__obligor_user__company.company_idWHERE (mortgage__obligor_user__company.company_name= %s ANDmortgage.originator_user_id= %s)' - /usr/lib/python2.4/site-packages/MySQLdb/cursors.py in execute
- else:
- self.messages.append((TypeError, m))
- self.errorhandler(self, TypeError, m)
- except:
- exc, value, tb = exc_info()
- del tb
- self.messages.append((exc, value))
- self.errorhandler(self, exc, value) ...
- self._executed = query
- self._warning_check()
- return r 141.
- def executemany(self, query, args):
143.
▶ Local vars
Variable Value
ListType
<type 'list'>
TupleType
<type 'tuple'>
args
['Trinity', 50001L]
exc
<class _mysql_exceptions.ProgrammingError at 0xb6d3cbfc>
exc_info
<built-in function exc_info>
query
'SELECT COUNT(DISTINCT(mortgage.mortgage_id)) FROMmortgageINNER JOINuser_infoASmortgage__obligor_userONmortgage.obligor_user_id=mortgage__obligor_user.user_idINNER JOINcompanyASmortgage__obligor_user__companyONmortgage__obligor_user.company_id=mortgage__obligor_user__company.company_idWHERE (mortgage__obligor_user__company.company_name= %s ANDmortgage.originator_user_id= %s)'
self
<MySQLdb.cursors.Cursor object at 0xb6c85a2c>
value
<_mysql_exceptions.ProgrammingError instance at 0xb6c85f4c>
- /usr/lib/python2.4/site-packages/MySQLdb/connections.py in defaulterrorhandler
26.
- """
- error = errorclass, errorvalue
- if cursor:
- cursor.messages.append(error)
- else:
- connection.messages.append(error)
- raise errorclass, errorvalue ... 34. 35.
- class Connection(_mysql.connection): 37.
- """MySQL Database Connection Object"""
39.
▶ Local vars
Change History (5)
comment:1 by , 19 years ago
| Summary: | [multip-db] Filters with nested foreign keys across databases fail → [multi-db] Filters with nested foreign keys across databases fail |
|---|
comment:2 by , 19 years ago
comment:3 by , 19 years ago
| Keywords: | multi-db added |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
| Version: | SVN → other branch |
comment:4 by , 18 years ago
This sounds exactly like the issue I had, it's to do with the select clause being in one SQL dialect and some other stuff being in another (sorry for being vague I don't have the details to hand). Ticket 3885 has some more detail with some preliminary findings into causes.
comment:5 by , 17 years ago
| Resolution: | → wontfix |
|---|---|
| Status: | new → closed |
The multi-db is no longer active. Alternative approaches are being considered for trunk.
Sorry... I haven't pasted a code block in here before...let me do that the correct way...I'll preview from now on ;)
Settings file:
DATABASE_ENGINE = 'mysql' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'. DATABASE_NAME = 'djangodb' # Or path to database file if using sqlite3. DATABASE_USER = 'root' # Not used with sqlite3. DATABASE_PASSWORD = '' # Not used with sqlite3. DATABASE_HOST = 'somehost' # Set to empty string for localhost. Not used with sqlite3. DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. OTHER_DATABASES = { 'mortgagedb': { 'DATABASE_NAME': 'mortgagedb', 'DATABASE_USER': 'root', 'DATABASE_PASSWORD': '', 'MODELS': ['mortgagedb'] }, 'userdb': { 'DATABASE_NAME': 'userdb', 'DATABASE_USER': 'root', 'DATABASE_PASSWORD': '', 'MODELS': ['userdb'] }, . . .Models Code:
Users Model: class Company(models.Model): company_id = models.AutoField(primary_key=True) company_name = models.CharField(blank=True, maxlength=150) ....other properties class UserInfo(models.Model): user_id = models.AutoField(primary_key=True) login = models.CharField(blank=True, maxlength=765) first_name = models.CharField(blank=True, maxlength=60) middle_name = models.CharField(blank=True, maxlength=60) last_name = models.CharField(blank=True, maxlength=60) company = models.ForeignKey(Company,related_name="company_users") Loans Model: (import users model up top) class Mortgage(models.Model): mortgage_id = models.AutoField(primary_key=True) property = models.ForeignKey(Property) obligor_user = models.ForeignKey(UserInfo, null=True)View Code
paramsnew = {} paramsnew['obligor_user__company__company_name']= request.POST['company_name'] # __istartswith fails too, as well as trying to do company ids with __in mortgages = Mortgage.objects.filter(**params).distinct() #Mortgage.objects.filter(**params) fails too