summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnssi Kääriäinen <akaariai@gmail.com>2014-01-19 11:30:26 +0200
committerAnssi Kääriäinen <akaariai@gmail.com>2014-01-20 10:52:57 +0200
commita9f171151814c03fcb0dcc87b153397e90562ea2 (patch)
treebbcad9252745c4529c45d1d786e992a51f5dd04b
parent457c16d0d607f8940cfc75bedafa1f122e17bcb9 (diff)
Fixed Oracle in lookup when more than 1000 params
Refs #21821.
-rw-r--r--django/db/models/lookups.py36
1 files changed, 34 insertions, 2 deletions
diff --git a/django/db/models/lookups.py b/django/db/models/lookups.py
index 2b9a2e722c..bc2539b051 100644
--- a/django/db/models/lookups.py
+++ b/django/db/models/lookups.py
@@ -1,4 +1,5 @@
from copy import copy
+from itertools import repeat
import inspect
from django.conf import settings
@@ -77,8 +78,8 @@ class Lookup(RegisterLookupMixin):
lhs = lhs or self.lhs
return qn.compile(lhs)
- def process_rhs(self, qn, connection, rhs=None):
- value = rhs or self.rhs
+ def process_rhs(self, qn, connection):
+ value = self.rhs
# Due to historical reasons there are a couple of different
# ways to produce sql here. get_compiler is likely a Query
# instance, _as_sql QuerySet and as_sql just something with
@@ -95,6 +96,12 @@ class Lookup(RegisterLookupMixin):
else:
return self.get_db_prep_lookup(value, connection)
+ def rhs_is_direct_value(self):
+ return not(
+ hasattr(self.rhs, 'as_sql') or
+ hasattr(self.rhs, '_as_sql') or
+ hasattr(self.rhs, 'get_compiler'))
+
def relabeled_clone(self, relabels):
new = copy(self)
new.lhs = new.lhs.relabeled_clone(relabels)
@@ -186,6 +193,31 @@ class In(BuiltinLookup):
def get_rhs_op(self, connection, rhs):
return 'IN %s' % rhs
+
+ def as_sql(self, qn, connection):
+ max_in_list_size = connection.ops.max_in_list_size()
+ if self.rhs_is_direct_value() and (max_in_list_size and
+ len(self.rhs) > max_in_list_size):
+ rhs, rhs_params = self.process_rhs(qn, connection)
+ lhs, lhs_params = self.process_lhs(qn, connection)
+ in_clause_elements = ['(']
+ params = []
+ for offset in xrange(0, len(rhs_params), max_in_list_size):
+ if offset > 0:
+ in_clause_elements.append(' OR ')
+ in_clause_elements.append('%s IN (' % lhs)
+ params.extend(lhs_params)
+ group_size = min(len(rhs_params) - offset, max_in_list_size)
+ param_group = ', '.join(repeat('%s', group_size))
+ in_clause_elements.append(param_group)
+ in_clause_elements.append(')')
+ params.extend(rhs_params[offset: offset + max_in_list_size])
+ in_clause_elements.append(')')
+ return ''.join(in_clause_elements), params
+ else:
+ return super(In, self).as_sql(qn, connection)
+
+
default_lookups['in'] = In