Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#24654 closed Bug (fixed)

infinite loop caused by ordering, triggered by relational primary key construct

Reported by: elmar bucher Owned by: Simon Charette
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


Source Code file

from django.db import models

class Organism( models.Model ):
    organism = models.SlugField( primary_key=True )
    class Meta:
        ordering = ["organism"]

class TheLoop( models.Model ):
    loop = models.SlugField( primary_key=True )
    target_organism = models.ForeignKey( Organism )
    host_organism = models.ForeignKey( Organism )    
    class Meta:
        ordering = ["target_organism","host_organism"]  #"loop" 

class InfinitLoop( models.Model):
    infinity = models.SlugField( primary_key=True )
    loop = models.ForeignKey( TheLoop )
    class Meta:
        ordering = ["loop"]  #"infinity" file

from django.test import TestCase
from .models import  InfinitLoop , TheLoop 

class InfinitLoopTests( TestCase ):
    def test_infinitloop( self ):
        #print( TheLoop.objects.all() )
        print( InfinitLoop.objects.all() )

Trace Back

(djangovenv) JOSHUA ~/src/django/tests $ PYTHONPATH=..:$PYTHONPATH python infinitloop
Testing against Django installed in '/Users/buchere/src/django/django'
Creating test database for alias 'default'...
Creating test database for alias 'other'...
ERROR: test_infinitloop (infinitloop.test.InfinitLoopTests)
Traceback (most recent call last):
  File "/Users/buchere/src/django/tests/infinitloop/", line 8, in test_infinitloop
    print( InfinitLoop.objects.all() )
  File "/Users/buchere/src/django/django/db/models/", line 234, in __repr__
    data = list(self[:REPR_OUTPUT_SIZE + 1])
  File "/Users/buchere/src/django/django/db/models/", line 258, in __iter__
  File "/Users/buchere/src/django/django/db/models/", line 1061, in _fetch_all
    self._result_cache = list(self.iterator())
  File "/Users/buchere/src/django/django/db/models/", line 52, in __iter__
    results = compiler.execute_sql()
  File "/Users/buchere/src/django/django/db/models/sql/", line 824, in execute_sql
    sql, params = self.as_sql()
  File "/Users/buchere/src/django/django/db/models/sql/", line 373, in as_sql
    extra_select, order_by, group_by = self.pre_sql_setup()
  File "/Users/buchere/src/django/django/db/models/sql/", line 49, in pre_sql_setup
    order_by = self.get_order_by()
  File "/Users/buchere/src/django/django/db/models/sql/", line 285, in get_order_by
    field, self.query.get_meta(), default_order=asc))
  File "/Users/buchere/src/django/django/db/models/sql/", line 570, in find_ordering_name
    order, already_seen))
  File "/Users/buchere/src/django/django/db/models/sql/", line 564, in find_ordering_name
    raise FieldError('Infinite loop caused by ordering.')
django.core.exceptions.FieldError: Infinite loop caused by ordering.

Ran 1 test in 0.002s

FAILED (errors=1)
Destroying test database for alias 'default'...
Destroying test database for alias 'other'...
(djangovenv) JOSHUA ~/src/django/tests $ 

Change History (10)

comment:1 by Tim Graham, 9 years ago

Triage Stage: UnreviewedAccepted

The models didn't appear obviously invalid to me (but if they are, maybe we could add a system check about it). I could reproduce the traceback with the code above.

comment:2 by Simon Charette, 9 years ago

I think the models are valid.

Tim, if you still have the code used to reproduce around could try removing both ordering clause and printing the following query InfinitLoop.objects.order_by('loop__target_organism', 'loop__host_organism').

comment:3 by Tim Graham, 9 years ago

With all three Meta.ordering attributes removed (not sure if you wanted that or just the bottom two):

SELECT "infiniteloop_infinitloop"."infinity", "infiniteloop_infinitloop"."loop_id" FROM "infiniteloop_infinitloop" INNER JOIN "infiniteloop_theloop" ON ( "infiniteloop_infinitloop"."loop_id" = "infiniteloop_theloop"."loop" ) ORDER BY "infiniteloop_theloop"."target_organism_id" ASC, "infiniteloop_theloop"."host_organism_id" ASC

With just the bottom two removed:

SELECT "infiniteloop_infinitloop"."infinity", "infiniteloop_infinitloop"."loop_id" FROM "infiniteloop_infinitloop" INNER JOIN "infiniteloop_theloop" ON ( "infiniteloop_infinitloop"."loop_id" = "infiniteloop_theloop"."loop" ) INNER JOIN "infiniteloop_organism" ON ( "infiniteloop_theloop"."target_organism_id" = "infiniteloop_organism"."organism" ) INNER JOIN "infiniteloop_organism" T4 ON ( "infiniteloop_theloop"."host_organism_id" = T4."organism" ) ORDER BY "infiniteloop_organism"."organism" ASC, T4."organism" ASC

comment:4 by Simon Charette, 9 years ago

Owner: changed from nobody to Simon Charette
Status: newassigned

Thanks Tim! Will look into this.

comment:5 by Simon Charette, 9 years ago

Has patch: set

comment:6 by Simon Charette, 9 years ago

Patch needs improvement: set

comment:7 by Simon Charette, 9 years ago

Patch needs improvement: unset

comment:8 by Tim Graham, 9 years ago

Triage Stage: AcceptedReady for checkin

comment:9 by Simon Charette <charette.s@…>, 9 years ago

Resolution: fixed
Status: assignedclosed

In b44ed40:

Fixed #24654 -- Based ordering circular references detection on columns.

Thanks to Elmar Bucher for the report and Tim for the review.

comment:10 by elmar bucher, 9 years ago

Thank you to Simon Charette and Tim Graham for taking care and fixing the bug so promptly!

Note: See TracTickets for help on using tickets.
Back to Top