Ticket #14244: patch.txt

File patch.txt, 3.3 KB (added by rlynch, 4 years ago)

Patch of proposed fix

Line 
1Index: django/db/models/sql/where.py
2===================================================================
3--- django/db/models/sql/where.py       (revision 13680)
4+++ django/db/models/sql/where.py       (working copy)
5@@ -178,7 +178,32 @@
6                 raise EmptyResultSet
7             if extra:
8                 return ('%s IN %s' % (field_sql, extra), params)
9-            return ('%s IN (%s)' % (field_sql, ', '.join(['%s'] * len(params))),
10+            #break up in clauses over 1000 itens.  This is to specifially support an Oracle limit of 1000 items in an in clause
11+            MAX_IN_PARAMS = 1000
12+            if len(params) > MAX_IN_PARAMS:
13+                in_clause_elements = [] #used to concatinate elements later
14+                is_first = True #avoid putting ' OR ' in front of first in clause group
15+                cur_min = 0 #starting point of current parameter elements
16+                in_clause_elements.append('(')
17+                while cur_min <= len(params):
18+                    if not is_first:
19+                        in_clause_elements.append(' OR ')
20+                    else:
21+                        is_first = False
22+                    num_params = 0
23+                    if cur_min + MAX_IN_PARAMS > len(params):
24+                        #we are at the end so only use the remaining parameters
25+                        num_params = len(params) - cur_min
26+                    else:
27+                        #use full 1000 paramaters
28+                        num_params = MAX_IN_PARAMS
29+                    in_clause_elements.append('(%s IN (%s))' % (field_sql, ', '.join(['%s'] * num_params)))
30+                    cur_min += MAX_IN_PARAMS
31+                   
32+                in_clause_elements.append(')')
33+                return ''.join(in_clause_elements), params
34+            else:
35+                return ('%s IN (%s)' % (field_sql, ', '.join(['%s'] * len(params))),
36                     params)
37         elif lookup_type in ('range', 'year'):
38             return ('%s BETWEEN %%s and %%s' % field_sql, params)
39Index: tests/modeltests/where/__init__.py
40===================================================================
41Index: tests/modeltests/where/models.py
42===================================================================
43--- tests/modeltests/where/models.py    (revision 0)
44+++ tests/modeltests/where/models.py    (revision 0)
45@@ -0,0 +1,4 @@
46+from django.db import models
47+
48+class A(models.Model):
49+    x = models.IntegerField()
50Index: tests/modeltests/where/tests.py
51===================================================================
52--- tests/modeltests/where/tests.py     (revision 0)
53+++ tests/modeltests/where/tests.py     (revision 0)
54@@ -0,0 +1,20 @@
55+from django.test import TestCase
56+
57+from models import A
58+
59+class WhereTest(TestCase):
60+    '''
61+    Unfortunately this test does not work because SQLite3 has a predefined limit of 1000 parameters in a query.
62+    SQLite3 does expose a setting to increase this but it is only exposed in the C or Python APSW libraries.
63+    http://www.sqlite.org/capi3ref.html#SQLITE_LIMIT_ATTACHED
64+    '''
65+   
66+    def testSimple(self):       
67+        xs = []
68+        #create 1001 A types
69+        for i in range(1001):
70+            A.objects.create(x=i)     
71+            xs.append(i)
72+       
73+        queried = A.objects.filter(x__in=xs)
74+        self.assertEquals(len(queried), 1001)
Back to Top