Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
"""
|
|
|
|
Code to manage the creation and SQL rendering of 'where' constraints.
|
|
|
|
"""
|
2011-10-18 00:56:18 +08:00
|
|
|
|
|
|
|
from __future__ import absolute_import
|
|
|
|
|
2012-05-23 02:26:46 +08:00
|
|
|
import collections
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
import datetime
|
2010-09-17 03:53:41 +08:00
|
|
|
from itertools import repeat
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
|
2013-02-10 23:15:49 +08:00
|
|
|
from django.conf import settings
|
|
|
|
from django.db.models.fields import DateTimeField, Field
|
2012-06-02 09:13:36 +08:00
|
|
|
from django.db.models.sql.datastructures import EmptyResultSet, Empty
|
2012-02-23 03:40:27 +08:00
|
|
|
from django.db.models.sql.aggregates import Aggregate
|
2012-07-21 00:53:11 +08:00
|
|
|
from django.utils.six.moves import xrange
|
2013-02-10 23:15:49 +08:00
|
|
|
from django.utils import timezone
|
|
|
|
from django.utils import tree
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
|
|
|
|
# Connection types
|
|
|
|
AND = 'AND'
|
|
|
|
OR = 'OR'
|
|
|
|
|
2009-01-05 19:47:14 +08:00
|
|
|
class EmptyShortCircuit(Exception):
|
|
|
|
"""
|
|
|
|
Internal exception used to indicate that a "matches nothing" node should be
|
|
|
|
added to the where-clause.
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
class WhereNode(tree.Node):
|
|
|
|
"""
|
|
|
|
Used to represent the SQL where-clause.
|
|
|
|
|
|
|
|
The class is tied to the Query class that created it (in order to create
|
2008-06-12 11:37:13 +08:00
|
|
|
the correct SQL).
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
|
|
|
|
The children in this tree are usually either Q-like objects or lists of
|
2012-02-23 03:40:27 +08:00
|
|
|
[table_alias, field_name, db_type, lookup_type, value_annotation, params].
|
|
|
|
However, a child could also be any class with as_sql() and relabel_aliases() methods.
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
"""
|
|
|
|
default = AND
|
|
|
|
|
2008-07-04 14:42:58 +08:00
|
|
|
def add(self, data, connector):
|
|
|
|
"""
|
|
|
|
Add a node to the where-tree. If the data is a list or tuple, it is
|
2010-09-14 05:44:21 +08:00
|
|
|
expected to be of the form (obj, lookup_type, value), where obj is
|
|
|
|
a Constraint object, and is then slightly munged before being stored
|
|
|
|
(to avoid storing any reference to field objects). Otherwise, the 'data'
|
|
|
|
is stored unchanged and can be any class with an 'as_sql()' method.
|
2008-07-04 14:42:58 +08:00
|
|
|
"""
|
|
|
|
if not isinstance(data, (list, tuple)):
|
|
|
|
super(WhereNode, self).add(data, connector)
|
|
|
|
return
|
|
|
|
|
2009-01-05 19:47:14 +08:00
|
|
|
obj, lookup_type, value = data
|
2012-05-23 02:26:46 +08:00
|
|
|
if isinstance(value, collections.Iterator):
|
2009-03-08 11:32:16 +08:00
|
|
|
# Consume any generators immediately, so that we can determine
|
|
|
|
# emptiness and transform any non-empty values correctly.
|
|
|
|
value = list(value)
|
2009-01-05 19:47:14 +08:00
|
|
|
|
2012-02-23 03:40:27 +08:00
|
|
|
# The "value_annotation" parameter is used to pass auxilliary information
|
2009-01-05 19:47:14 +08:00
|
|
|
# about the value(s) to the query construction. Specifically, datetime
|
|
|
|
# and empty values need special handling. Other types could be used
|
|
|
|
# here in the future (using Python types is suggested for consistency).
|
2013-02-10 23:15:49 +08:00
|
|
|
if (isinstance(value, datetime.datetime)
|
|
|
|
or (isinstance(obj.field, DateTimeField) and lookup_type != 'isnull')):
|
2012-02-23 03:40:27 +08:00
|
|
|
value_annotation = datetime.datetime
|
2009-01-08 13:16:21 +08:00
|
|
|
elif hasattr(value, 'value_annotation'):
|
2012-02-23 03:40:27 +08:00
|
|
|
value_annotation = value.value_annotation
|
2008-07-04 14:42:58 +08:00
|
|
|
else:
|
2012-02-23 03:40:27 +08:00
|
|
|
value_annotation = bool(value)
|
2009-01-05 19:47:14 +08:00
|
|
|
|
2009-12-22 23:18:51 +08:00
|
|
|
if hasattr(obj, "prepare"):
|
|
|
|
value = obj.prepare(lookup_type, value)
|
|
|
|
|
2012-02-23 03:40:27 +08:00
|
|
|
super(WhereNode, self).add(
|
|
|
|
(obj, lookup_type, value_annotation, value), connector)
|
2008-07-04 14:42:58 +08:00
|
|
|
|
2009-12-22 23:18:51 +08:00
|
|
|
def as_sql(self, qn, connection):
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
"""
|
|
|
|
Returns the SQL version of the where clause and the value to be
|
2012-05-26 10:55:33 +08:00
|
|
|
substituted in. Returns '', [] if this node matches everything,
|
|
|
|
None, [] if this node is empty, and raises EmptyResultSet if this
|
|
|
|
node can't match anything.
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
"""
|
2012-05-26 10:55:33 +08:00
|
|
|
# Note that the logic here is made slightly more complex than
|
|
|
|
# necessary because there are two kind of empty nodes: Nodes
|
|
|
|
# containing 0 children, and nodes that are known to match everything.
|
|
|
|
# A match-everything node is different than empty node (which also
|
|
|
|
# technically matches everything) for backwards compatibility reasons.
|
|
|
|
# Refs #5261.
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
result = []
|
|
|
|
result_params = []
|
2012-05-26 10:55:33 +08:00
|
|
|
everything_childs, nothing_childs = 0, 0
|
|
|
|
non_empty_childs = len(self.children)
|
|
|
|
|
2008-07-04 14:42:58 +08:00
|
|
|
for child in self.children:
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
try:
|
|
|
|
if hasattr(child, 'as_sql'):
|
2009-12-22 23:18:51 +08:00
|
|
|
sql, params = child.as_sql(qn=qn, connection=connection)
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
else:
|
2008-07-04 14:42:58 +08:00
|
|
|
# A leaf node in the tree.
|
2009-12-22 23:18:51 +08:00
|
|
|
sql, params = self.make_atom(child, qn, connection)
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
except EmptyResultSet:
|
2012-05-26 10:55:33 +08:00
|
|
|
nothing_childs += 1
|
|
|
|
else:
|
|
|
|
if sql:
|
|
|
|
result.append(sql)
|
|
|
|
result_params.extend(params)
|
|
|
|
else:
|
|
|
|
if sql is None:
|
|
|
|
# Skip empty childs totally.
|
|
|
|
non_empty_childs -= 1
|
|
|
|
continue
|
|
|
|
everything_childs += 1
|
|
|
|
# Check if this node matches nothing or everything.
|
|
|
|
# First check the amount of full nodes and empty nodes
|
|
|
|
# to make this node empty/full.
|
|
|
|
if self.connector == AND:
|
|
|
|
full_needed, empty_needed = non_empty_childs, 1
|
|
|
|
else:
|
|
|
|
full_needed, empty_needed = 1, non_empty_childs
|
|
|
|
# Now, check if this node is full/empty using the
|
|
|
|
# counts.
|
|
|
|
if empty_needed - nothing_childs <= 0:
|
|
|
|
if self.negated:
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
return '', []
|
2012-05-26 10:55:33 +08:00
|
|
|
else:
|
|
|
|
raise EmptyResultSet
|
|
|
|
if full_needed - everything_childs <= 0:
|
2008-07-04 14:42:58 +08:00
|
|
|
if self.negated:
|
2012-05-26 10:55:33 +08:00
|
|
|
raise EmptyResultSet
|
|
|
|
else:
|
|
|
|
return '', []
|
2008-07-04 14:42:58 +08:00
|
|
|
|
2012-05-26 10:55:33 +08:00
|
|
|
if non_empty_childs == 0:
|
|
|
|
# All the child nodes were empty, so this one is empty, too.
|
|
|
|
return None, []
|
2008-07-04 14:42:58 +08:00
|
|
|
conn = ' %s ' % self.connector
|
|
|
|
sql_string = conn.join(result)
|
|
|
|
if sql_string:
|
2012-05-26 10:55:33 +08:00
|
|
|
if self.negated:
|
2012-07-03 15:29:10 +08:00
|
|
|
# Some backends (Oracle at least) need parentheses
|
|
|
|
# around the inner SQL in the negated case, even if the
|
|
|
|
# inner SQL contains just a single expression.
|
2012-07-02 03:49:38 +08:00
|
|
|
sql_string = 'NOT (%s)' % sql_string
|
|
|
|
elif len(result) > 1:
|
|
|
|
sql_string = '(%s)' % sql_string
|
2008-07-04 14:42:58 +08:00
|
|
|
return sql_string, result_params
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
|
2009-12-22 23:18:51 +08:00
|
|
|
def make_atom(self, child, qn, connection):
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
"""
|
2012-02-23 03:40:27 +08:00
|
|
|
Turn a tuple (Constraint(table_alias, column_name, db_type),
|
|
|
|
lookup_type, value_annotation, params) into valid SQL.
|
|
|
|
|
|
|
|
The first item of the tuple may also be an Aggregate.
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
|
|
|
|
Returns the string for the SQL fragment and the parameters to use for
|
|
|
|
it.
|
|
|
|
"""
|
2012-02-23 03:40:27 +08:00
|
|
|
lvalue, lookup_type, value_annotation, params_or_value = child
|
|
|
|
if isinstance(lvalue, Constraint):
|
2009-12-22 23:18:51 +08:00
|
|
|
try:
|
|
|
|
lvalue, params = lvalue.process(lookup_type, params_or_value, connection)
|
|
|
|
except EmptyShortCircuit:
|
|
|
|
raise EmptyResultSet
|
2012-02-23 03:40:27 +08:00
|
|
|
elif isinstance(lvalue, Aggregate):
|
|
|
|
params = lvalue.field.get_db_prep_lookup(lookup_type, params_or_value, connection)
|
2009-12-22 23:18:51 +08:00
|
|
|
else:
|
2012-02-23 03:40:27 +08:00
|
|
|
raise TypeError("'make_atom' expects a Constraint or an Aggregate "
|
|
|
|
"as the first item of its 'child' argument.")
|
|
|
|
|
2009-01-05 19:47:14 +08:00
|
|
|
if isinstance(lvalue, tuple):
|
|
|
|
# A direct database column lookup.
|
2013-02-10 23:15:49 +08:00
|
|
|
field_sql, field_params = self.sql_for_columns(lvalue, qn, connection), []
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
else:
|
2009-01-05 19:47:14 +08:00
|
|
|
# A smart object with an as_sql() method.
|
2013-02-10 23:15:49 +08:00
|
|
|
field_sql, field_params = lvalue.as_sql(qn, connection)
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
|
2013-02-10 23:15:49 +08:00
|
|
|
is_datetime_field = value_annotation is datetime.datetime
|
|
|
|
cast_sql = connection.ops.datetime_cast_sql() if is_datetime_field else '%s'
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
|
2009-01-29 18:46:36 +08:00
|
|
|
if hasattr(params, 'as_sql'):
|
2009-12-22 23:18:51 +08:00
|
|
|
extra, params = params.as_sql(qn, connection)
|
2009-01-29 18:46:36 +08:00
|
|
|
cast_sql = ''
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
else:
|
|
|
|
extra = ''
|
|
|
|
|
2013-02-10 23:15:49 +08:00
|
|
|
params = field_params + params
|
|
|
|
|
2009-12-22 23:18:51 +08:00
|
|
|
if (len(params) == 1 and params[0] == '' and lookup_type == 'exact'
|
|
|
|
and connection.features.interprets_empty_strings_as_nulls):
|
|
|
|
lookup_type = 'isnull'
|
2012-02-23 03:40:27 +08:00
|
|
|
value_annotation = True
|
2009-12-22 23:18:51 +08:00
|
|
|
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
if lookup_type in connection.operators:
|
2009-02-08 19:14:56 +08:00
|
|
|
format = "%s %%s %%s" % (connection.ops.lookup_cast(lookup_type),)
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
return (format % (field_sql,
|
2009-02-08 19:14:56 +08:00
|
|
|
connection.operators[lookup_type] % cast_sql,
|
|
|
|
extra), params)
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
|
|
|
|
if lookup_type == 'in':
|
2012-02-23 03:40:27 +08:00
|
|
|
if not value_annotation:
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
raise EmptyResultSet
|
|
|
|
if extra:
|
|
|
|
return ('%s IN %s' % (field_sql, extra), params)
|
2010-09-17 03:53:41 +08:00
|
|
|
max_in_list_size = connection.ops.max_in_list_size()
|
|
|
|
if max_in_list_size and len(params) > max_in_list_size:
|
|
|
|
# Break up the params list into an OR of manageable chunks.
|
|
|
|
in_clause_elements = ['(']
|
|
|
|
for offset in xrange(0, len(params), max_in_list_size):
|
|
|
|
if offset > 0:
|
|
|
|
in_clause_elements.append(' OR ')
|
|
|
|
in_clause_elements.append('%s IN (' % field_sql)
|
|
|
|
group_size = min(len(params) - offset, max_in_list_size)
|
|
|
|
param_group = ', '.join(repeat('%s', group_size))
|
|
|
|
in_clause_elements.append(param_group)
|
|
|
|
in_clause_elements.append(')')
|
|
|
|
in_clause_elements.append(')')
|
|
|
|
return ''.join(in_clause_elements), params
|
|
|
|
else:
|
|
|
|
return ('%s IN (%s)' % (field_sql,
|
|
|
|
', '.join(repeat('%s', len(params)))),
|
|
|
|
params)
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
elif lookup_type in ('range', 'year'):
|
|
|
|
return ('%s BETWEEN %%s and %%s' % field_sql, params)
|
2013-02-10 23:15:49 +08:00
|
|
|
elif is_datetime_field and lookup_type in ('month', 'day', 'week_day',
|
|
|
|
'hour', 'minute', 'second'):
|
|
|
|
tzname = timezone.get_current_timezone_name() if settings.USE_TZ else None
|
|
|
|
sql, tz_params = connection.ops.datetime_extract_sql(lookup_type, field_sql, tzname)
|
|
|
|
return ('%s = %%s' % sql, tz_params + params)
|
2009-02-08 13:08:06 +08:00
|
|
|
elif lookup_type in ('month', 'day', 'week_day'):
|
2013-02-10 23:15:49 +08:00
|
|
|
return ('%s = %%s'
|
|
|
|
% connection.ops.date_extract_sql(lookup_type, field_sql), params)
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
elif lookup_type == 'isnull':
|
2013-02-11 17:28:46 +08:00
|
|
|
assert value_annotation in (True, False), "Invalid value_annotation for isnull"
|
|
|
|
return ('%s IS %sNULL' % (field_sql, ('' if value_annotation else 'NOT ')), ())
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
elif lookup_type == 'search':
|
|
|
|
return (connection.ops.fulltext_search_sql(field_sql), params)
|
|
|
|
elif lookup_type in ('regex', 'iregex'):
|
|
|
|
return connection.ops.regex_lookup(lookup_type) % (field_sql, cast_sql), params
|
|
|
|
|
|
|
|
raise TypeError('Invalid lookup_type: %r' % lookup_type)
|
|
|
|
|
2009-12-22 23:18:51 +08:00
|
|
|
def sql_for_columns(self, data, qn, connection):
|
2009-01-05 19:47:14 +08:00
|
|
|
"""
|
|
|
|
Returns the SQL fragment used for the left-hand side of a column
|
|
|
|
constraint (for example, the "T1.foo" portion in the clause
|
2013-02-10 23:15:49 +08:00
|
|
|
"WHERE ... T1.foo = 6") and a list of parameters.
|
2009-01-05 19:47:14 +08:00
|
|
|
"""
|
|
|
|
table_alias, name, db_type = data
|
|
|
|
if table_alias:
|
|
|
|
lhs = '%s.%s' % (qn(table_alias), qn(name))
|
|
|
|
else:
|
|
|
|
lhs = qn(name)
|
|
|
|
return connection.ops.field_cast_sql(db_type) % lhs
|
|
|
|
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
def relabel_aliases(self, change_map, node=None):
|
|
|
|
"""
|
|
|
|
Relabels the alias values of any children. 'change_map' is a dictionary
|
|
|
|
mapping old (current) alias values to the new values.
|
|
|
|
"""
|
|
|
|
if not node:
|
|
|
|
node = self
|
|
|
|
for pos, child in enumerate(node.children):
|
|
|
|
if hasattr(child, 'relabel_aliases'):
|
|
|
|
child.relabel_aliases(change_map)
|
|
|
|
elif isinstance(child, tree.Node):
|
|
|
|
self.relabel_aliases(change_map, child)
|
2010-02-23 12:39:39 +08:00
|
|
|
elif isinstance(child, (list, tuple)):
|
2009-02-23 22:47:59 +08:00
|
|
|
if isinstance(child[0], (list, tuple)):
|
|
|
|
elt = list(child[0])
|
|
|
|
if elt[0] in change_map:
|
|
|
|
elt[0] = change_map[elt[0]]
|
|
|
|
node.children[pos] = (tuple(elt),) + child[1:]
|
|
|
|
else:
|
|
|
|
child[0].relabel_aliases(change_map)
|
|
|
|
|
2009-01-29 18:46:36 +08:00
|
|
|
# Check if the query value also requires relabelling
|
|
|
|
if hasattr(child[3], 'relabel_aliases'):
|
|
|
|
child[3].relabel_aliases(change_map)
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
|
2012-06-02 09:13:36 +08:00
|
|
|
def clone(self):
|
|
|
|
"""
|
|
|
|
Creates a clone of the tree. Must only be called on root nodes (nodes
|
|
|
|
with empty subtree_parents). Childs must be either (Contraint, lookup,
|
|
|
|
value) tuples, or objects supporting .clone().
|
|
|
|
"""
|
|
|
|
assert not self.subtree_parents
|
|
|
|
clone = self.__class__._new_instance(
|
|
|
|
children=[], connector=self.connector, negated=self.negated)
|
|
|
|
for child in self.children:
|
|
|
|
if isinstance(child, tuple):
|
|
|
|
clone.children.append(
|
|
|
|
(child[0].clone(), child[1], child[2], child[3]))
|
|
|
|
else:
|
|
|
|
clone.children.append(child.clone())
|
|
|
|
return clone
|
|
|
|
|
2012-10-24 05:04:37 +08:00
|
|
|
class EmptyWhere(WhereNode):
|
|
|
|
|
|
|
|
def add(self, data, connector):
|
|
|
|
return
|
|
|
|
|
|
|
|
def as_sql(self, qn=None, connection=None):
|
|
|
|
raise EmptyResultSet
|
|
|
|
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
class EverythingNode(object):
|
|
|
|
"""
|
|
|
|
A node that matches everything.
|
|
|
|
"""
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
def as_sql(self, qn=None, connection=None):
|
2012-05-26 10:55:33 +08:00
|
|
|
return '', []
|
Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-04-27 10:50:16 +08:00
|
|
|
|
|
|
|
def relabel_aliases(self, change_map, node=None):
|
|
|
|
return
|
2008-07-23 14:12:15 +08:00
|
|
|
|
2012-06-02 09:13:36 +08:00
|
|
|
def clone(self):
|
|
|
|
return self
|
|
|
|
|
2008-07-23 14:12:15 +08:00
|
|
|
class NothingNode(object):
|
|
|
|
"""
|
|
|
|
A node that matches nothing.
|
|
|
|
"""
|
2009-12-22 23:18:51 +08:00
|
|
|
def as_sql(self, qn=None, connection=None):
|
2008-07-23 14:12:15 +08:00
|
|
|
raise EmptyResultSet
|
|
|
|
|
|
|
|
def relabel_aliases(self, change_map, node=None):
|
|
|
|
return
|
|
|
|
|
2012-06-02 09:13:36 +08:00
|
|
|
def clone(self):
|
|
|
|
return self
|
|
|
|
|
2010-02-23 12:39:39 +08:00
|
|
|
class ExtraWhere(object):
|
|
|
|
def __init__(self, sqls, params):
|
|
|
|
self.sqls = sqls
|
|
|
|
self.params = params
|
2010-04-22 00:34:33 +08:00
|
|
|
|
2010-02-23 12:39:39 +08:00
|
|
|
def as_sql(self, qn=None, connection=None):
|
2012-04-09 08:43:08 +08:00
|
|
|
sqls = ["(%s)" % sql for sql in self.sqls]
|
2013-02-10 23:15:49 +08:00
|
|
|
return " AND ".join(sqls), list(self.params or ())
|
2010-02-23 12:39:39 +08:00
|
|
|
|
2012-06-02 09:13:36 +08:00
|
|
|
def clone(self):
|
|
|
|
return self
|
|
|
|
|
2009-01-05 19:47:14 +08:00
|
|
|
class Constraint(object):
|
|
|
|
"""
|
|
|
|
An object that can be passed to WhereNode.add() and knows how to
|
|
|
|
pre-process itself prior to including in the WhereNode.
|
|
|
|
"""
|
|
|
|
def __init__(self, alias, col, field):
|
|
|
|
self.alias, self.col, self.field = alias, col, field
|
|
|
|
|
2010-04-22 00:34:33 +08:00
|
|
|
def __getstate__(self):
|
|
|
|
"""Save the state of the Constraint for pickling.
|
|
|
|
|
|
|
|
Fields aren't necessarily pickleable, because they can have
|
|
|
|
callable default values. So, instead of pickling the field
|
|
|
|
store a reference so we can restore it manually
|
|
|
|
"""
|
|
|
|
obj_dict = self.__dict__.copy()
|
|
|
|
if self.field:
|
|
|
|
obj_dict['model'] = self.field.model
|
|
|
|
obj_dict['field_name'] = self.field.name
|
|
|
|
del obj_dict['field']
|
|
|
|
return obj_dict
|
|
|
|
|
|
|
|
def __setstate__(self, data):
|
|
|
|
"""Restore the constraint """
|
|
|
|
model = data.pop('model', None)
|
|
|
|
field_name = data.pop('field_name', None)
|
|
|
|
self.__dict__.update(data)
|
|
|
|
if model is not None:
|
|
|
|
self.field = model._meta.get_field(field_name)
|
|
|
|
else:
|
|
|
|
self.field = None
|
|
|
|
|
2009-12-22 23:18:51 +08:00
|
|
|
def prepare(self, lookup_type, value):
|
|
|
|
if self.field:
|
|
|
|
return self.field.get_prep_lookup(lookup_type, value)
|
|
|
|
return value
|
|
|
|
|
|
|
|
def process(self, lookup_type, value, connection):
|
2009-01-05 19:47:14 +08:00
|
|
|
"""
|
|
|
|
Returns a tuple of data suitable for inclusion in a WhereNode
|
|
|
|
instance.
|
|
|
|
"""
|
|
|
|
# Because of circular imports, we need to import this here.
|
|
|
|
from django.db.models.base import ObjectDoesNotExist
|
|
|
|
try:
|
|
|
|
if self.field:
|
2009-12-22 23:18:51 +08:00
|
|
|
params = self.field.get_db_prep_lookup(lookup_type, value,
|
|
|
|
connection=connection, prepared=True)
|
|
|
|
db_type = self.field.db_type(connection=connection)
|
2009-01-05 19:47:14 +08:00
|
|
|
else:
|
|
|
|
# This branch is used at times when we add a comparison to NULL
|
|
|
|
# (we don't really want to waste time looking up the associated
|
|
|
|
# field object at the calling location).
|
2009-12-22 23:18:51 +08:00
|
|
|
params = Field().get_db_prep_lookup(lookup_type, value,
|
|
|
|
connection=connection, prepared=True)
|
2009-01-05 19:47:14 +08:00
|
|
|
db_type = None
|
|
|
|
except ObjectDoesNotExist:
|
|
|
|
raise EmptyShortCircuit
|
|
|
|
|
|
|
|
return (self.alias, self.col, db_type), params
|
|
|
|
|
2009-12-22 23:18:51 +08:00
|
|
|
def relabel_aliases(self, change_map):
|
|
|
|
if self.alias in change_map:
|
|
|
|
self.alias = change_map[self.alias]
|
2012-06-02 09:13:36 +08:00
|
|
|
|
|
|
|
def clone(self):
|
|
|
|
new = Empty()
|
|
|
|
new.__class__ = self.__class__
|
|
|
|
new.alias, new.col, new.field = self.alias, self.col, self.field
|
|
|
|
return new
|